SQL → NoSQL

Apostila completa de NoSQL para quem já domina SQL

Você já sabe modelar tabelas, escrever JOINs e pensar em ACID. Esta apostila usa esse conhecimento como ponte: cada conceito NoSQL é apresentado em contraste com o mundo relacional que você conhece, do fundamento à arquitetura distribuída — sempre com o olho no que empresas realmente pedem em vagas e entrevistas.

10 módulosMongoDB · Redis · Cassandra · Neo4jDynamoDB · Elasticsearch · VetoriaisBoxes de entrevistaExercícios com gabarito
MÓDULO 01 · BÁSICO

O que é NoSQL e por que ele existe

Objetivo: entender o problema que o NoSQL resolve, quando usá-lo (e quando não), partindo do que você já sabe de SQL.

1.1 O mundo que você conhece: relacional

No modelo relacional, você projeta o esquema primeiro (tabelas, colunas, tipos, chaves estrangeiras), normaliza para eliminar redundância e confia em transações ACID para manter tudo consistente. Isso funciona maravilhosamente bem — tanto que bancos relacionais dominam há 50 anos e continuam sendo a escolha padrão para a maioria dos sistemas.

Mas por volta de 2005–2010, empresas como Google, Amazon e Facebook bateram em três paredes ao mesmo tempo:

NoSQL ("Not Only SQL") é o nome guarda-chuva para a família de bancos criados para atacar essas paredes, cada um sacrificando algo do modelo relacional (geralmente JOINs, esquema rígido ou consistência forte) em troca de escala horizontal, flexibilidade de esquema ou modelos de dados especializados.

🔁 Tradução SQL → NoSQL

NoSQL não é "SQL melhorado" nem "SQL obsoleto". É um conjunto de trade-offs diferentes. A pergunta profissional nunca é "SQL ou NoSQL é melhor?", e sim "quais garantias este caso de uso exige, e quais posso relaxar?". Empresas maduras usam os dois lado a lado (persistência poliglota — Módulo 9).

1.2 As cinco diferenças fundamentais

DimensãoRelacional (o que você sabe)NoSQL (o que muda)
EsquemaDefinido antes (schema-on-write); alterações via migraçãoFlexível/dinâmico (schema-on-read); documentos da mesma coleção podem ter campos diferentes
EscalaVertical por padrão; sharding é possível mas complexoHorizontal por design: adicionar máquinas baratas ao cluster
RelacionamentosJOINs resolvidos pelo banco em tempo de consultaEm geral não há JOIN; os dados são pré-agrupados conforme o padrão de leitura (desnormalização)
ConsistênciaACID forte por padrãoFrequentemente BASE / consistência eventual configurável (Módulo 3)
Modelo de dadosUm só: tabelasQuatro principais: documento, chave-valor, coluna larga, grafo

1.3 A mudança mental mais importante

Se você levar uma única ideia deste módulo, que seja esta:

💡 Conceito-chave

No relacional, você modela a partir dos dados ("quais entidades existem?") e as consultas se adaptam. No NoSQL, você modela a partir das consultas ("quais perguntas a aplicação fará?") e os dados se adaptam. Chama-se query-driven design. Quase todo erro de iniciante em NoSQL vem de modelar como se fosse relacional.

1.4 Quando usar (e quando NÃO usar) NoSQL

Sinais de que NoSQL ajudaSinais de que relacional é melhor
Volume/tráfego além de um servidor; necessidade real de escala horizontalDados cabem confortavelmente em um servidor (99% dos sistemas!)
Esquema muda com frequência ou é heterogêneoEsquema estável e bem conhecido
Padrões de acesso simples e conhecidos (buscar por chave, por usuário...)Consultas ad-hoc imprevisíveis, relatórios com muitos JOINs
Latência de milissegundos em escala global; cache; sessões; rankingTransações complexas multi-entidade (financeiro, estoque crítico)
Dados naturalmente em documento, grafo ou série temporalIntegridade referencial é requisito central
💼 Mercado de trabalho

Pergunta clássica de entrevista júnior/pleno: "Quando você escolheria NoSQL em vez de um banco relacional?" A resposta que reprova é "quando precisa de performance" (vago e muitas vezes falso). A resposta que aprova cita trade-offs concretos: padrão de acesso conhecido + escala horizontal + tolerância a consistência eventual, e reconhece que Postgres resolve a maioria dos casos. Demonstrar que você não usa NoSQL por hype vale mais que decorar features.

✏️ Exercício 1 — Você é o arquiteto

Para cada sistema, diga se começaria com relacional, NoSQL ou ambos: (a) sistema interno de RH com 500 funcionários; (b) feed de rede social com 50 milhões de usuários; (c) carrinho de compras de e-commerce; (d) sistema bancário de transferências.

Gabarito: (a) Relacional — escala pequena, dados estruturados, relatórios ad-hoc. (b) NoSQL (documento/coluna larga) — escala massiva, leitura por padrão conhecido, tolera eventualidade. (c) Híbrido comum: catálogo/carrinho em documento ou chave-valor (Redis/DynamoDB), pedido fechado em relacional. (d) Relacional — ACID é inegociável para o livro-razão; NoSQL pode entrar em cache e análise.

MÓDULO 02 · BÁSICO

Os 4 tipos de bancos NoSQL (+ os especializados)

Objetivo: reconhecer cada família, seu modelo mental, seus campeões de mercado e o caso de uso ideal de cada uma.

2.1 Documento o mais usado

Armazena documentos JSON/BSON — objetos completos, com campos aninhados e listas. É o tipo mais próximo de como sua aplicação já enxerga os dados: um "usuário" com endereços e preferências vira um documento, não cinco tabelas.

// Um documento em MongoDB — compare com as 3–4 tabelas que isso exigiria em SQL
{
  "_id": "u123",
  "nome": "Ana Souza",
  "email": "ana@exemplo.com",
  "enderecos": [
    { "tipo": "casa", "cidade": "Recife", "cep": "50000-000" }
  ],
  "preferencias": { "tema": "escuro", "notificacoes": true }
}

2.2 Chave-valor o mais rápido

O modelo mais simples que existe: um dicionário gigante e distribuído. Você grava um valor sob uma chave e o recupera pela chave — nada de consultas por conteúdo. Essa simplicidade permite latências de microssegundos e escala quase ilimitada.

SET  sessao:8f3a  '{"userId":"u123","carrinho":[...]}'  EX 3600
GET  sessao:8f3a

2.3 Coluna larga (wide-column) o de escala massiva

Pense em uma tabela onde cada linha é localizada por uma chave de partição e pode conter milhares de colunas ordenadas, e onde o cluster distribui partições entre dezenas ou centenas de nós automaticamente. É o modelo para escrita pesada e volume gigantesco — telemetria, mensagens, eventos.

2.4 Grafo o dos relacionamentos

Aqui os relacionamentos são cidadãos de primeira classe: nós (entidades) e arestas (relações) armazenados diretamente, com travessia em tempo constante por salto. Perguntas que em SQL exigiriam JOINs recursivos brutais ("amigos dos amigos dos amigos que compraram X") são triviais.

2.5 Os especializados que o mercado adora

TipoExemplosPara quê
Busca (search engine)Elasticsearch, OpenSearchBusca textual com relevância, filtros facetados, logs e observabilidade
Série temporalInfluxDB, TimescaleDB, PrometheusMétricas, sensores, dados financeiros com janela de tempo
VetorialPinecone, Qdrant, Weaviate, pgvector, MilvusBusca semântica por similaridade de embeddings — a base de RAG e apps de IA
💼 Mercado de trabalho — qual aprender primeiro?

Minha recomendação, justificada, para o mercado em 2026:

  • 1º MongoDB — é o NoSQL mais citado em vagas de backend/full-stack (stack MEAN/MERN, muito comum em startups e consultorias). Aprender MongoDB ensina o modelo de documento, que é a porta de entrada conceitual.
  • 2º Redis — aparece em praticamente toda arquitetura de produção como cache/sessão/fila. É o complemento perfeito: você raramente compete com quem sabe "MongoDB e Redis bem".
  • 3º depende da trilha: Engenharia de Dados → Cassandra/DynamoDB e Elasticsearch; Backend em cloud AWS → DynamoDB; áreas de fraude/recomendação/IA → Neo4j e bancos vetoriais (em alta por causa de RAG).

Elasticsearch merece menção honrosa: em vagas de DevOps/SRE (stack ELK) e e-commerce ele é constante.

✏️ Exercício 2 — Classifique o problema

Qual família você escolheria? (a) autocomplete de busca em loja virtual; (b) armazenar leituras de 100 mil sensores a cada segundo; (c) "clientes que compraram junto também levaram..."; (d) guardar o token de sessão do usuário logado.

Gabarito: (a) Elasticsearch/OpenSearch; (b) coluna larga (Cassandra/Scylla) ou série temporal; (c) grafo (Neo4j) — ou vetorial se for por similaridade semântica; (d) chave-valor (Redis) com TTL.

MÓDULO 03 · INTERMEDIÁRIO

Teoria essencial: CAP, BASE e sistemas distribuídos

Objetivo: dominar o vocabulário teórico que sustenta todo o resto — e que é o assunto favorito de entrevistas pleno/sênior.

3.1 O Teorema CAP

Em um sistema distribuído (dados espalhados por vários nós), três propriedades entram em tensão:

O teorema diz: quando ocorre uma partição de rede, você é obrigado a escolher entre C e A. Como falhas de rede são inevitáveis em qualquer sistema distribuído real, P não é opcional — a escolha real é: durante uma falha, prefiro responder errado (AP) ou não responder (CP)?

EscolhaComportamento na partiçãoExemplosFaz sentido para
CPRecusa/atrasa respostas para nunca devolver dado desatualizadoMongoDB (padrão), HBase, Zookeeper, etcdSaldo, estoque, configuração crítica
APSempre responde, aceitando dados possivelmente antigos que convergem depoisCassandra, DynamoDB, CouchDB, RiakFeed, carrinho, curtidas, telemetria
⚠️ Pegadinha de entrevista

Dizer que um banco "é CA" costuma ser errado em contexto distribuído: sem tolerância a partição, o sistema simplesmente não é distribuído de forma confiável (um Postgres de nó único é "CA" apenas porque não há partição possível). Outra nuance que impressiona entrevistadores: CAP descreve o comportamento durante a falha; fora dela, sistemas como Cassandra permitem ajustar consistência por operação (seção 3.4), então o rótulo CP/AP é um espectro, não uma prisão.

3.2 ACID vs BASE

Você conhece ACID. O NoSQL popularizou o modelo BASE:

Consistência eventual na prática: você curte uma foto; sua curtida grava na réplica de São Paulo; um amigo em Frankfurt pode não vê-la por 200 ms. Para curtidas, ótimo negócio. Para saldo bancário, inaceitável. Saber classificar cada dado do domínio nessa régua é uma habilidade de arquiteto.

Entre os extremos existem níveis intermediários que caem em entrevista sênior: read-your-own-writes (você sempre vê o que você mesmo escreveu), monotonic reads (você nunca vê o tempo "voltar") e causal consistency (efeitos nunca aparecem antes das causas).

3.3 Replicação e particionamento (sharding)

Duas técnicas ortogonais que todo NoSQL distribuído combina:

Consistent hashing avançado

Se você distribuir chaves com hash(chave) % N_nós, adicionar 1 nó remaneja quase todas as chaves — desastre. O consistent hashing coloca nós e chaves em um "anel" de hash: cada chave pertence ao primeiro nó no sentido horário. Adicionar/remover um nó move apenas ~1/N das chaves. Cassandra, DynamoDB e o Redis Cluster (via 16384 hash slots, uma variação) usam essa ideia. Citar consistent hashing em uma entrevista de system design é meio caminho para a aprovação.

3.4 Quóruns: consistência ajustável avançado

Em sistemas de replicação sem líder com N réplicas, você escolhe W (quantas confirmam a escrita) e R (quantas são consultadas na leitura). A regra de ouro:

W + R > N   →  leitura e escrita se sobrepõem em ao menos 1 réplica
             →  a leitura sempre enxerga a escrita mais recente (consistência forte)

Exemplo clássico com N=3:
W=2, R=2  →  forte, tolera 1 nó fora           (equilíbrio comum)
W=1, R=1  →  máxima velocidade, eventual        (telemetria, likes)
W=3, R=1  →  escrita cara, leitura rápida/forte (lê muito, escreve pouco)

Cassandra expõe isso literalmente (QUORUM, ONE, ALL, LOCAL_QUORUM...) e o Módulo 6 mostra na prática.

3.5 Como escritas ficam rápidas: o LSM-Tree avançado

Bancos relacionais tradicionais usam B-Trees: escrever exige localizar e alterar a página certa no disco (acesso aleatório). Cassandra, RocksDB, ScyllaDB e o motor WiredTiger do MongoDB (parcialmente) usam LSM-Trees (Log-Structured Merge Trees):

  1. A escrita vai para um log sequencial em disco (commit log — rapidíssimo) e para uma estrutura em memória (memtable);
  2. Quando a memtable enche, é despejada em disco como um arquivo imutável e ordenado (SSTable);
  3. Um processo de compaction mescla SSTables em segundo plano, descartando versões antigas e registros deletados (tombstones).

Resultado: escritas viram I/O sequencial (ordens de magnitude mais rápido), ao custo de leituras potencialmente consultarem várias SSTables (mitigado por bloom filters) e do custo contínuo de compaction. Esse trade-off explica por que Cassandra devora escritas.

💼 Mercado de trabalho

Perguntas reais de entrevista deste módulo: "Explique o teorema CAP com um exemplo prático", "O que é consistência eventual e quando ela é aceitável?", "Como funciona consistent hashing e que problema resolve?", "Por que Cassandra é tão rápido em escrita?" (resposta: LSM-Tree + escrita sem leitura prévia + sem líder). Este é o módulo que separa quem "usou MongoDB uma vez" de quem entende sistemas distribuídos — e é o que destrava faixas salariais de pleno para sênior.

✏️ Exercício 3 — Quórum na prática

Um cluster tem N=5 réplicas. (a) Com W=3 e R=3, a leitura é fortemente consistente? (b) Quantos nós podem cair sem impedir escritas? (c) Se o requisito é "leituras baratas e frequentes, escritas raras", que configuração você sugere?

Gabarito: (a) Sim: 3+3=6 > 5, há sobreposição garantida. (b) Escritas exigem 3 confirmações, então toleram 2 nós fora. (c) W=5 (ou W=4), R=1 — paga-se caro na escrita rara para ler de um único nó com consistência.

MÓDULO 04 · INTERMEDIÁRIO → AVANÇADO

MongoDB a fundo

Objetivo: sair do CRUD e chegar a agregações, modelagem profissional, índices, transações e arquitetura de cluster — o pacote que vagas de backend pedem.

4.1 Vocabulário e CRUD com tradução SQL

SQLMongoDB
databasedatabase
tabelacoleção (collection)
linhadocumento (BSON)
colunacampo (field)
PRIMARY KEY_id (ObjectId automático)
JOIN$lookup (limitado) ou embedding
-- SQL                                        // MongoDB
INSERT INTO users (nome, idade)               db.users.insertOne({ nome: "Ana", idade: 28 })
VALUES ('Ana', 28);

SELECT * FROM users WHERE idade > 25;         db.users.find({ idade: { $gt: 25 } })

SELECT nome FROM users                        db.users.find(
WHERE cidade = 'Recife'                         { cidade: "Recife" },
ORDER BY idade DESC LIMIT 10;                  { nome: 1, _id: 0 }
                                              ).sort({ idade: -1 }).limit(10)

UPDATE users SET idade = 29                   db.users.updateOne(
WHERE nome = 'Ana';                             { nome: "Ana" }, { $set: { idade: 29 } })

DELETE FROM users WHERE idade < 18;           db.users.deleteMany({ idade: { $lt: 18 } })

Operadores de consulta essenciais: $gt/$gte/$lt/$lte/$ne, $in/$nin, $and/$or/$not, $exists, $regex, $elemMatch (para arrays de objetos). Operadores de update: $set, $inc, $push, $pull, $addToSet, $unset.

4.2 Modelagem: embedding vs referencing o coração do MongoDB

A decisão que define o sucesso de um projeto MongoDB: aninhar (embed) ou referenciar?

// EMBEDDING — endereços dentro do usuário (1 leitura traz tudo)
{ _id: "u1", nome: "Ana", enderecos: [ { rua: "..." }, { rua: "..." } ] }

// REFERENCING — pedidos apontam para o usuário (como uma FK)
{ _id: "p1", userId: "u1", total: 250.0 }
Use embedding quando…Use referencing quando…
Os dados são lidos juntos quase sempre (relação "contém")O lado "muitos" cresce sem limite (pedidos, comentários, logs)
O relacionamento é 1:1 ou 1:poucosO dado é acessado/atualizado de forma independente
O subdocumento não faz sentido sozinhoVários documentos compartilham o mesmo dado (evita duplicar N vezes)
⚠️ Antipadrão nº 1: arrays sem limite

Documentos têm limite de 16 MB, e arrays gigantes degradam tudo (cada update reescreve/move o documento). Embutir "todos os comentários do post" funciona no protótipo e explode em produção. Soluções de mercado: referenciar, ou o padrão bucket (agrupar itens em documentos de tamanho fixo, ex.: 1 documento por post por dia), ou o padrão subset (embutir só os 10 mais recentes e referenciar o resto).

Outros padrões que caem em entrevista: Extended Reference (duplicar 2–3 campos do documento referenciado para evitar o segundo fetch — ex.: guardar nomeCliente dentro do pedido), Computed (pré-calcular agregados na escrita), Schema Versioning (campo schemaVersion para migrações graduais) e Polymorphic (documentos de "tipos" diferentes na mesma coleção).

4.3 Aggregation Pipeline o "GROUP BY" turbinado

O pipeline de agregação é uma sequência de estágios que transformam documentos — o equivalente (muito mais poderoso) de GROUP BY + subqueries:

// Total de vendas por cidade em 2025, top 5 — pense em cada estágio como um WHERE/GROUP/ORDER encadeado
db.pedidos.aggregate([
  { $match: { data: { $gte: ISODate("2025-01-01") }, status: "pago" } },
  { $group: { _id: "$cliente.cidade",
             total: { $sum: "$valor" },
             pedidos: { $sum: 1 } } },
  { $sort: { total: -1 } },
  { $limit: 5 },
  { $project: { cidade: "$_id", total: 1, pedidos: 1, _id: 0 } }
])

Estágios essenciais: $match (WHERE — sempre o mais cedo possível para usar índice), $group, $sort, $project (SELECT de campos), $unwind (explode array em documentos), $lookup (LEFT JOIN — use com moderação), $facet (várias agregações em uma passada), $merge/$out (materializar resultado em coleção).

4.4 Índices e performance

db.users.createIndex({ email: 1 }, { unique: true })     // único
db.pedidos.createIndex({ userId: 1, data: -1 })          // composto
db.produtos.createIndex({ descricao: "text" })           // texto
db.lojas.createIndex({ localizacao: "2dsphere" })        // geoespacial
db.sessoes.createIndex({ criadoEm: 1 }, { expireAfterSeconds: 3600 })  // TTL!
db.pedidos.find({ userId: "u1" }).explain("executionStats")

4.5 Transações, Replica Sets e Sharding avançado

Transações: operações em um único documento são atômicas por natureza (e a boa modelagem resolve 90% dos casos assim — se você precisa de transações multi-documento o tempo todo, provavelmente modelou como relacional). Desde a versão 4.x existem transações ACID multi-documento com a sintaxe session.startTransaction(), mas com custo de performance real.

Replica Set (alta disponibilidade): 1 primário (recebe escritas) + N secundários replicando o oplog. Se o primário cai, uma eleição (protocolo tipo Raft) promove um secundário em segundos. Parâmetros que caem em entrevista: writeConcern (w:1 rápido vs w:"majority" durável) e readPreference (primary consistente vs secondaryPreferred escala leitura aceitando atraso de replicação).

Sharded Cluster (escala horizontal): mongos (roteador) + config servers + shards (cada um é um replica set). A shard key é irreversível na prática e define tudo:

💼 Mercado de trabalho

O que as vagas realmente testam sobre MongoDB: (1) decidir embedding vs referencing em um cenário dado; (2) escrever um aggregation pipeline; (3) explicar por que uma consulta está lenta e propor índice (regra ESR + explain); (4) writeConcern/readPreference; (5) o problema da shard key monotônica. Projeto de portfólio que impressiona: uma API REST (Node/Nest ou Spring) com MongoDB usando agregações reais, índices justificados no README e um teste de carga mostrando o antes/depois do índice.

✏️ Exercício 4 — Modelagem de e-commerce

Modele: usuários, produtos, avaliações de produtos (podem chegar a milhares por produto) e pedidos. O app mostra a página do produto com as 5 avaliações mais recentes e a nota média.

Gabarito (uma boa resposta): produtos com padrão subset (array ultimasAvaliacoes com as 5 mais recentes) + campos computed (notaMedia, totalAvaliacoes atualizados com $inc na escrita); coleção avaliacoes separada referenciando produtoId com índice {produtoId: 1, data: -1}; pedidos referenciando userId mas com extended reference (nome do produto e preço congelados dentro do item do pedido — dado histórico não deve mudar se o produto mudar).

MÓDULO 05 · INTERMEDIÁRIO → AVANÇADO

Redis a fundo

Objetivo: dominar as estruturas de dados, os padrões de cache que toda empresa usa, e os tópicos avançados (persistência, cluster, locks) de entrevistas sênior.

5.1 O que o Redis realmente é

Redis é um servidor de estruturas de dados em memória. Tudo vive na RAM (latência de microssegundos), com persistência opcional em disco. Ele é (no núcleo) single-threaded: um loop de eventos processa comandos um a um — o que elimina locks e torna cada operação atômica por natureza. É provavelmente a peça de infraestrutura mais onipresente do backend moderno.

5.2 As estruturas de dados (o superpoder)

EstruturaComandos-chaveCaso de uso matador
StringSET/GET/INCR/EXCache de resposta, contadores, feature flags
HashHSET/HGET/HGETALLObjetos (perfil do usuário) com acesso por campo
ListLPUSH/RPOP/BRPOPFilas de trabalho simples, timeline recente
SetSADD/SISMEMBER/SINTERTags, deduplicação, "quem visitou hoje", interseções
Sorted SetZADD/ZRANGE/ZRANKRanking/leaderboard, filas com prioridade, rate limiting por janela
StreamXADD/XREADGROUP/XACKLog de eventos estilo Kafka-lite, com consumer groups
Bitmap / HyperLogLogSETBIT / PFADD/PFCOUNTPresença diária de milhões de usuários em KB; contagem aproximada de únicos com 12 KB
GeoGEOADD/GEOSEARCH"Motoristas num raio de 2 km"
# Leaderboard de um jogo em 3 comandos
ZADD ranking 4850 "ana"
ZINCRBY ranking 120 "ana"              # somou pontos
ZREVRANGE ranking 0 9 WITHSCORES       # top 10 — O(log N)

# Rate limiting: máx. 100 requisições/minuto por usuário
INCR rate:u123:202607071431            # chave por usuário+minuto
EXPIRE rate:u123:202607071431 60       # se retorno do INCR > 100 → bloqueia

5.3 Padrões de cache obrigatório em entrevista

Os três desastres clássicos de cache (e como evitar)

💡 Invalidação de cache

"Há apenas duas coisas difíceis em computação: invalidação de cache e dar nomes às coisas." Estratégias reais: TTL curto e aceitar janela de staleness (padrão mais comum); invalidar explicitamente no update (DEL chave após o commit no banco — nesta ordem); versão na chave (produto:42:v7). Em entrevista, mostre que sabe que consistência cache-banco é sempre eventual e que se dimensiona a janela conforme o negócio.

5.4 Persistência: RDB vs AOF avançado

RDB (snapshot)AOF (append-only file)
O que éFoto binária do dataset a cada X minLog de todos os comandos de escrita
Perda máximaMinutos (desde o último snapshot)~1 s com appendfsync everysec (padrão)
RestartRápidoMais lento (reexecuta o log; mitigado por rewrite)
Produção sériaOs dois juntos — RDB para backup/restore rápido, AOF para durabilidade

Mesmo assim, trate o Redis como armazenamento recuperável, não como fonte de verdade primária de dados críticos — esse enquadramento em entrevista demonstra maturidade.

5.5 Alta disponibilidade e escala avançado

Lock distribuído

# Lock simples e correto para 1 instância:
SET lock:pedido:42 <token-aleatorio> NX PX 30000
# NX = só se não existir; PX = expira em 30s (evita deadlock se o dono morrer)
# liberar: DEL somente se o token for seu (script Lua para atomicidade)

Para múltiplos nós existe o algoritmo Redlock — cite-o em entrevista, mas mencione também que ele é controverso (críticas famosas de Martin Kleppmann sobre garantias em partições e pausas de GC). Conhecer a controvérsia é sinal de senioridade.

💼 Mercado de trabalho

Redis raramente é "a vaga" — ele é a pergunta de sistema em todas as vagas. Clássicos: "Como você implementaria rate limiting?", "O que fazer quando uma chave quente expira?" (stampede), "Redis pode perder dados?" (RDB/AOF), "Como faria um ranking em tempo real?" (sorted set). Projeto de portfólio: adicione ao seu projeto MongoDB uma camada de cache-aside com invalidação e um rate limiter — e documente a decisão de TTL.

✏️ Exercício 5 — Escolha a estrutura

Qual estrutura Redis para: (a) contar visitantes únicos do mês com pouquíssima memória, aceitando ~0,8% de erro; (b) fila de e-mails com workers concorrentes e confirmação de processamento; (c) "usuários online agora"; (d) top 100 produtos mais vendidos do dia?

Gabarito: (a) HyperLogLog (PFADD/PFCOUNT); (b) Stream com consumer group (XADD/XREADGROUP/XACK) — List com BRPOP vale para casos simples, mas sem ACK; (c) Set com TTL ou bitmap por minuto; (d) Sorted Set com ZINCRBY na venda e ZREVRANGE 0 99.

MÓDULO 06 · AVANÇADO

Cassandra e o mundo coluna larga

Objetivo: entender a arquitetura sem líder, dominar a modelagem query-first e a consistência ajustável — o território da engenharia de dados e de sistemas de escala extrema.

6.1 Arquitetura: o anel sem mestre

Cassandra implementa as ideias do paper Dynamo (Amazon, 2007) com o modelo de dados do Bigtable (Google). Não há primário: todos os nós são iguais, organizados em um anel de consistent hashing (Módulo 3). Qualquer nó recebe qualquer requisição (vira o coordinator dela) e a roteia para as réplicas donas da partição. Nós se descobrem e monitoram via protocolo gossip. Consequências:

6.2 Modelo de dados e a chave primária de duas partes

CREATE TABLE mensagens_por_canal (
  canal_id     uuid,
  enviada_em   timeuuid,
  autor        text,
  conteudo     text,
  PRIMARY KEY ((canal_id), enviada_em)
) WITH CLUSTERING ORDER BY (enviada_em DESC);
⚠️ A pegadinha do CQL

CQL parece SQL, mas WHERE autor = 'ana' sem a partition key não funciona (ou exige ALLOW FILTERING, que varre o cluster inteiro — jamais em produção). Não há JOIN, nem GROUP BY livre, nem agregações arbitrárias. Se a consulta não segue a estrutura da chave, a resposta não é "otimizar a query" — é criar outra tabela.

6.3 Modelagem query-first: desnormalize sem medo

Em Cassandra o fluxo profissional é: listar as consultas da aplicação → criar uma tabela por consulta, duplicando dados. Escrita é barata; a aplicação (ou materialized views, com ressalvas) mantém as cópias:

-- Q1: mensagens de um canal por tempo        -- Q2: mensagens de um autor por tempo
mensagens_por_canal                            mensagens_por_autor
PRIMARY KEY ((canal_id), enviada_em)           PRIMARY KEY ((autor_id), enviada_em)

Para quem vem de SQL isso parece pecado (3ª forma normal, adeus). A regra aqui inverte: disco é barato, latência é cara.

Dimensionando partições

Partições não devem crescer sem limite (alvo prático: até ~100 MB / algumas centenas de milhares de linhas). Séries temporais usam bucketing: incluir o período na partition key — PRIMARY KEY ((sensor_id, dia), hora) — quebrando o histórico infinito em partições diárias.

6.4 Consistência ajustável na prática

-- Por operação, você escolhe o nível:
CONSISTENCY ONE;           -- 1 réplica confirma: máxima velocidade (telemetria)
CONSISTENCY QUORUM;        -- maioria: com W=QUORUM e R=QUORUM → leitura forte
CONSISTENCY LOCAL_QUORUM;  -- maioria do datacenter local (padrão multi-região)
CONSISTENCY ALL;           -- todas: consistência máxima, disponibilidade mínima

Mecanismos de reparo que caem em entrevista sênior: hinted handoff (nó guarda escrita destinada a vizinho caído e entrega quando ele volta), read repair (divergência detectada na leitura é corrigida) e anti-entropy repair (comparação periódica via árvores de Merkle — o famoso nodetool repair).

🧠 Muito avançado: tombstones

DELETE em LSM-Tree não apaga — grava um tombstone (lápide) que esconde o dado até a compaction. Milhões de tombstones numa partição (padrão fila é o exemplo clássico: insere e deleta sem parar) fazem leituras varrerem lápides e derrubam o cluster. Por isso "fila em Cassandra" é um antipadrão célebre — resposta pronta para entrevistas.

💼 Mercado de trabalho

Cassandra/ScyllaDB aparece em vagas de engenharia de dados, fintechs de alto volume, telecom e big techs — salários costumam ser mais altos porque o funil de quem domina é estreito. Perguntas reais: "Diferença entre partition key e clustering column", "Por que ALLOW FILTERING é proibido?", "Como modelar série temporal sem partição infinita?" (bucketing), "O que são tombstones?". DynamoDB (Módulo 8) usa os mesmos conceitos — aprender um praticamente destrava o outro.

✏️ Exercício 6 — Modele para a consulta

App de rastreamento de entregas: a consulta principal é "últimas posições do veículo X no dia Y, mais recentes primeiro". Milhares de veículos, 1 posição a cada 5 s. Modele a tabela.

Gabarito: CREATE TABLE posicoes_por_veiculo_dia (veiculo_id uuid, dia date, ts timestamp, lat double, lon double, PRIMARY KEY ((veiculo_id, dia), ts)) WITH CLUSTERING ORDER BY (ts DESC); — bucketing diário limita a partição (~17k linhas/dia), a consulta vira leitura sequencial de uma única partição.

MÓDULO 07 · AVANÇADO

Bancos de grafos com Neo4j

Objetivo: pensar em nós e relacionamentos, escrever Cypher com fluência e reconhecer os problemas onde grafos vencem qualquer outro modelo.

7.1 O modelo: property graph

A mágica técnica chama-se index-free adjacency: cada nó guarda ponteiros físicos diretos para seus relacionamentos. Atravessar de um nó a seus vizinhos é O(1) independentemente do tamanho total do banco — enquanto cada JOIN em SQL paga uma busca em índice que cresce com a tabela. Em consultas de profundidade 4+ (amigo de amigo de amigo...), a diferença é de segundos para milissegundos.

7.2 Cypher com tradução SQL

// Criar dados — a sintaxe desenha o grafo: (nó)-[relação]->(nó)
CREATE (ana:Pessoa {nome: "Ana"})-[:TRABALHA_EM]->(:Empresa {nome: "TechCorp"})

// "SELECT com JOIN": colegas de trabalho da Ana
MATCH (a:Pessoa {nome: "Ana"})-[:TRABALHA_EM]->(e)<-[:TRABALHA_EM]-(colega)
RETURN colega.nome, e.nome

// O impossível em SQL: caminho de qualquer profundidade (1 a 4 saltos)
MATCH caminho = (a:Pessoa {nome: "Ana"})-[:CONHECE*1..4]-(alvo:Pessoa {nome: "Bruno"})
RETURN caminho ORDER BY length(caminho) LIMIT 1

// Recomendação colaborativa em 4 linhas:
// "produtos comprados por quem comprou o que eu comprei, que eu ainda não tenho"
MATCH (eu:Cliente {id: "c1"})-[:COMPROU]->(p)<-[:COMPROU]-(outro)-[:COMPROU]->(rec)
WHERE NOT (eu)-[:COMPROU]->(rec)
RETURN rec.nome, count(*) AS forca ORDER BY forca DESC LIMIT 10

Repare: o MATCH descreve um padrão visual; a consulta de recomendação equivalente em SQL exigiria 3 self-joins numa tabela de compras com milhões de linhas.

7.3 Modelagem e performance

💼 Mercado de trabalho

Grafos são nicho, mas nicho bem pago: detecção de fraude em bancos e fintechs (contas ligadas por dispositivo/endereço/telefone formam anéis de fraude visíveis em grafo), motores de recomendação, e — em plena ascensão — grafos de conhecimento para IA (GraphRAG). Em entrevista, a killer answer para "quando usar grafo?" é: "quando a pergunta do negócio é sobre o relacionamento em si, especialmente com profundidade variável — se eu me pego escrevendo JOINs recursivos ou CTEs recursivas, é sinal de grafo".

✏️ Exercício 7 — Fraude em Cypher

Escreva a ideia de uma consulta que encontre pares de contas diferentes que compartilham o mesmo dispositivo E o mesmo telefone (indício forte de fraude).

Gabarito: MATCH (c1:Conta)-[:USA]->(d:Dispositivo)<-[:USA]-(c2:Conta), (c1)-[:TEM]->(t:Telefone)<-[:TEM]-(c2) WHERE c1.id < c2.id RETURN c1, c2, d, t — o padrão de "diamante" duplo é trivial em Cypher e brutal em SQL.

MÓDULO 08 · AVANÇADO

DynamoDB, Elasticsearch e bancos vetoriais

Objetivo: cobrir os três NoSQL "especiais" que mais aparecem em vagas — cloud AWS, busca/observabilidade e a onda de IA.

8.1 Amazon DynamoDB o NoSQL da AWS

Chave-valor/documento totalmente gerenciado e serverless: sem servidores para administrar, latência de milissegundos de um dígito em qualquer escala, cobrança por requisição (RCU/WCU) ou on-demand. Os conceitos são primos do Cassandra:

🧠 Muito avançado: single-table design

O padrão idiomático (e contraintuitivo) do DynamoDB: todas as entidades da aplicação em UMA tabela, com chaves genéricas PK/SK compostas por prefixos (PK="USER#u1", SK="PROFILE"; PK="USER#u1", SK="ORDER#2026-07-07#p9"). Um único Query por PK="USER#u1" traz o usuário e seus pedidos — o "JOIN" foi pré-computado no layout das chaves. Dominar single-table design (referência: Alex DeBrie, The DynamoDB Book) é diferencial real em vagas AWS.

Trade-off honesto: DynamoDB pune padrões de acesso imprevistos (mudar consulta = redesenhar chaves/GSI) e prende à AWS; em troca, zero operação e escala infinita previsível. Custo é por acesso, não por armazenamento — modele para minimizar RCUs.

8.2 Elasticsearch / OpenSearch busca e observabilidade

Motor de busca distribuído sobre Apache Lucene. A estrutura central é o índice invertido: em vez de "documento → palavras", armazena "palavra → documentos que a contêm" (como o índice remissivo de um livro) — por isso busca textual em bilhões de documentos responde em milissegundos.

// Busca com filtro e faceta em uma chamada:
GET /produtos/_search
{
  "query": { "bool": {
    "must":   [{ "match": { "titulo": "tenis corrida" } }],
    "filter": [{ "range": { "preco": { "lte": 500 } } }]   // filter não afeta score e é cacheado
  }},
  "aggs": { "por_marca": { "terms": { "field": "marca" } } }
}

Importante: Elasticsearch não é fonte primária de dados (consistência eventual por design, sem transações). O padrão de mercado é: dado mora no Postgres/Mongo e é indexado no ES via CDC (Debezium/Kafka) ou dual-write cuidadoso.

8.3 Bancos vetoriais a fronteira (IA/RAG)

Modelos de embedding transformam texto/imagem em vetores (listas de ~768–3072 números) onde proximidade geométrica = similaridade semântica. Um banco vetorial indexa milhões desses vetores e responde "os k mais parecidos com este" (k-NN) em milissegundos — a fundação do RAG (Retrieval-Augmented Generation), padrão dominante para dar conhecimento privado a LLMs.

💼 Mercado de trabalho

Três apostas com timing diferente: DynamoDB abre portas em qualquer empresa AWS-first (maioria das grandes no Brasil) e é presença constante em certificações AWS (Developer/Architect); Elasticsearch é o cavalo de troia para DevOps/SRE (ELK) e e-commerce; vetoriais são a habilidade mais nova e menos concorrida — "implementei RAG com busca híbrida e avaliação de recall" é uma frase que hoje diferencia currículos. Projeto de portfólio: um chatbot RAG sobre documentos seus, com pgvector, comparando busca puramente vetorial vs híbrida.

✏️ Exercício 8 — Arquitetura de e-commerce completa

Monte o time de bancos para um e-commerce grande: catálogo, busca com filtros, carrinho, pedidos/pagamentos, recomendação, logs.

Gabarito (arquitetura poliglota típica): catálogo em MongoDB (documentos flexíveis) ou Postgres; busca em Elasticsearch (indexado via CDC); carrinho/sessão em Redis (TTL) ou DynamoDB; pedidos/pagamentos em Postgres (ACID inegociável); recomendação em Neo4j ou vetorial; logs em OpenSearch. Essa resposta, com as justificativas, é literalmente uma questão de system design de entrevista.

MÓDULO 09 · MUITO AVANÇADO

Arquitetura, padrões e operação em produção

Objetivo: integrar tudo — padrões de arquitetura com múltiplos bancos, migrações, performance, segurança e observabilidade. O conteúdo de nível sênior/staff.

9.1 Persistência poliglota

Sistemas maduros não escolhem um banco — escolhem o banco certo para cada dado, aceitando o custo de operar vários. O critério profissional para adicionar (ou não) mais um banco à stack:

9.2 Sincronizando bancos: CDC e o problema do dual-write

Com vários bancos, surge a pergunta central: como manter o Elasticsearch/cache/vetorial em sincronia com a fonte de verdade?

⚠️ O antipadrão dual-write

Escrever no Postgres e depois no Elasticsearch direto no código da aplicação parece óbvio e está errado: se a segunda escrita falhar (deploy, timeout, crash), os sistemas divergem silenciosamente e não há transação que os una. Esse é um dos bugs de consistência mais comuns em produção.

Soluções de mercado, em ordem de robustez:

9.3 Event Sourcing e CQRS muito avançado

Repare como o NoSQL se encaixa: os read models do CQRS são exatamente o "uma tabela por consulta" do Cassandra e o "documento moldado pela tela" do MongoDB. CQRS é a versão arquitetural do query-driven design do Módulo 1. Em entrevista, conecte esses pontos — é o tipo de síntese que marca candidatos sêniores.

9.4 Migrações: do relacional para NoSQL (e evolução de esquema)

9.5 Performance e capacity planning

9.6 Segurança o que derruba empresas

9.7 Observabilidade e operação

💼 Mercado de trabalho

Este módulo é o conteúdo de entrevistas de system design sênior: "como você manteria o índice de busca sincronizado?" (CDC/outbox, nunca dual-write), "como migraria do Oracle para NoSQL sem downtime?" (strangler + shadow reads), "o que monitoraria num cluster Redis?" (evictions, memória, hit ratio). Para DevOps/SRE, as seções 9.6 e 9.7 são o dia a dia da função. Uma resposta que cite percentis, backpressure e o antipadrão dual-write coloca você automaticamente na conversa de nível sênior.

✏️ Exercício 9 — Diagnóstico de produção

Sintoma: às 9h de segunda, o p99 do Redis salta de 1 ms para 800 ms e o banco relacional atrás dele satura. O hit ratio do cache caiu de 97% para 60%. O que provavelmente aconteceu e como prevenir?

Gabarito: cache avalanche/stampede — chaves populadas juntas (ex.: no deploy de sexta, com TTL uniforme de 72h) expiraram juntas; a recomputação simultânea saturou o banco e enfileirou o Redis. Prevenção: TTL com jitter aleatório, lock de recomputação por chave (single flight), aquecimento de cache pós-deploy e alarme sobre hit ratio.

MÓDULO 10 · CARREIRA

Mercado de trabalho: roadmap, entrevistas e portfólio

Objetivo: converter o conhecimento dos módulos anteriores em aprovação — roadmap por trilha, banco de perguntas reais com respostas e projetos que impressionam.

10.1 Roadmap por trilha de carreira

TrilhaPrioridade de estudoO que as vagas pedem na prática
Backend / Full-stackMongoDB → Redis → (DynamoDB se AWS)Modelagem de documentos, agregações, índices, cache-aside, rate limiting, sessões. Módulos 4 e 5 são 80% do que cai.
Engenharia de DadosCassandra/DynamoDB → Elasticsearch → CDC (Debezium/Kafka)Modelagem query-first, particionamento, pipelines de sincronização, séries temporais. Módulos 3, 6, 8 e 9.2.
DevOps / SRERedis (operação) → Elasticsearch/ELK → operação de clustersFailover, backup/restore, métricas e alarmes, capacity planning, segurança. Módulos 5.4–5.5, 8.2 e 9.5–9.7.
IA / ML EngineeringVetoriais (pgvector) → Redis (cache de LLM) → MongoDBRAG, busca híbrida, avaliação de recall, cache semântico. Módulo 8.3.

Plano de 8 semanas sugerido (para quem sai do SQL): semanas 1–2, Módulos 1–3 + MongoDB local rodando (Docker) com CRUD; semanas 3–4, Módulo 4 completo + projeto API; semanas 5–6, Módulo 5 + camada de cache no projeto; semana 7, Módulos 6–8 em nível conceitual (profundo apenas no da sua trilha); semana 8, Módulo 9 + simulados de entrevista deste módulo.

10.2 Banco de perguntas de entrevista (com a resposta que aprova)

Nível júnior/pleno — "Qual a diferença entre SQL e NoSQL?"

Evite a resposta decorada ("um tem tabelas, outro não"). Estruture em trade-offs: esquema (rígido vs flexível), escala (vertical vs horizontal nativa), consistência (ACID vs frequentemente eventual/ajustável) e modelagem (a partir dos dados vs a partir das consultas). Feche dizendo que a escolha é por caso de uso e que ambos convivem na mesma arquitetura.

Pleno — "Como você modelaria um blog no MongoDB?"

Mostre o raciocínio, não só o resultado: liste as consultas (página do post com autor e comentários recentes; listagem por tag; perfil do autor). Proposta: posts com autor via extended reference (id + nome denormalizado), comentários com padrão subset (últimos 10 embutidos, resto em coleção própria), índice {tags: 1, publicadoEm: -1}. Mencione o limite de 16 MB e por que comentários ilimitados não podem ser todos embutidos.

Pleno — "Para que você usaria Redis além de cache?"

Sessões distribuídas, rate limiting (INCR+EXPIRE ou sorted set por janela deslizante), filas e pub/sub, leaderboards (sorted sets), locks distribuídos (SET NX PX), contadores e deduplicação (sets/HyperLogLog), geobusca. Cite um caso que você implementou — especificidade vale mais que a lista.

Sênior — "Explique o teorema CAP e onde MongoDB e Cassandra se posicionam"

Defina C, A e P; enfatize que a escolha só existe durante a partição. MongoDB: CP por padrão (primário único; na partição, o lado minoritário para de aceitar escritas). Cassandra: AP por design, mas com consistência ajustável por operação — com QUORUM/QUORUM obtém-se leitura forte (W+R>N). Bônus: mencione que CAP é simplificação e cite PACELC (na ausência de partição, o trade-off é latência vs consistência).

Sênior — "Como manter Elasticsearch sincronizado com o banco principal?"

Descarte dual-write explicando o problema (falha parcial sem transação entre sistemas). Proponha CDC com Debezium lendo o WAL/oplog e publicando em Kafka, consumidores idempotentes indexando no ES; alternativa sem acesso ao log: transactional outbox. Mencione reindexação completa como plano de recuperação e monitoramento de lag.

Sênior/system design — "Projete o backend de um chat estilo WhatsApp"

Estrutura esperada: mensagens em coluna larga (Cassandra/Scylla — o caso do Discord) com PRIMARY KEY ((canal_id, bucket), msg_id DESC); presença/últimos vistos em Redis (TTL); busca de mensagens em Elasticsearch via CDC; contadores de não lidas em Redis com reconciliação; entrega via fila/stream. Justifique cada escolha com os trade-offs dos módulos 3–8 — o entrevistador avalia o raciocínio, não a stack exata.

Armadilha — "NoSQL é mais rápido que SQL?"

Resposta madura: "depende do padrão de acesso". Por chave conhecida em escala, sim (Redis/Dynamo); consultas ad-hoc com joins, o relacional com bons índices costuma vencer. NoSQL fica rápido porque restringe as consultas ao que a modelagem pré-computou. Quem responde "sim" seco falha; quem explica o porquê passa.

10.3 Projetos de portfólio que geram entrevista

  1. API de e-commerce (MongoDB + Redis): catálogo com agregações, índices justificados no README (com prints de explain() antes/depois), cache-aside com invalidação, rate limiting. Diferencial: teste de carga (k6) documentado.
  2. Pipeline de eventos (Cassandra ou DynamoDB): ingestão de telemetria simulada, modelagem query-first com bucketing, dashboard de leitura. Diferencial: documentar o dimensionamento de partição.
  3. Chatbot RAG (pgvector ou Qdrant): ingestão de documentos, busca híbrida (vetorial + BM25), avaliação simples de qualidade de retrieval. Diferencial: comparar as duas buscas com números.
  4. Detector de fraude em grafo (Neo4j): dataset sintético de contas/dispositivos, consultas de anéis de fraude, visualização. Nicho que chama atenção de fintechs.

Em todos: README explicando por que cada banco foi escolhido e quais trade-offs você aceitou. Recrutadores técnicos leem READMEs; a justificativa vale mais que o código.

10.4 Certificações e fontes para continuar

🏁 Síntese final da apostila

Se você internalizou três ideias, esta apostila cumpriu o papel: (1) NoSQL é um conjunto de trade-offs, não uma evolução do SQL; (2) modela-se a partir das consultas, aceitando duplicação; (3) em sistemas distribuídos, consistência, disponibilidade e latência estão em tensão permanente — e o trabalho do engenheiro é escolher conscientemente, dado por dado. Todo o resto — comandos, sintaxes, ferramentas — decorre dessas três e se aprende com a documentação aberta do lado.