System Design/02 - Componentes/Databases2 min
Document Store
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Guarda documentos semiestruturados (JSON, BSON) e permite consultar por dentro deles — a diferença essencial em relação a Key-Value Store, onde o valor é opaco.
{ "_id": 42, "nome": "Ana",
"enderecos": [ { "tipo": "casa", "cidade": "SP" } ],
"pedidos": [ { "id": 1, "total": 99.9 } ] }
Exemplos: MongoDB, CouchDB, DynamoDB, Firestore, Elasticsearch — e PostgreSQL com jsonb, que cobre boa parte dos casos com transação ACID por cima.
Embutir ou referenciar
A decisão de modelagem central:
| Embutir | Referenciar | |
|---|---|---|
| Leitura | Uma operação | Várias, ou $lookup |
| Atualização | Reescreve o documento | Independente |
| Bom quando | Relação 1:poucos, lido junto | 1:muitos ilimitado, dado compartilhado |
| Risco | Documento cresce sem limite | Volta o custo de junção |
A regra prática: embuta o que é sempre lido junto e tem tamanho limitado. Comentários de um post podem ser milhares — referencie. Endereços de um usuário são poucos — embuta.
Trade-offs
Schema flexível é o argumento de venda e a fonte da dívida. Sem validação na escrita, o mesmo campo aparece como "idade": 30, "idade": "30" e ausente — e a aplicação precisa lidar com todas as variações para sempre. Bancos de documento modernos oferecem validação de schema justamente porque essa liberdade se mostrou cara.
O limite de tamanho do documento é real (16 MB no MongoDB) e é atingido por arrays que crescem sem controle — o unbounded array é o antipadrão de modelagem mais comum.
Junções existem ($lookup) e são caras: o modelo não foi feito para elas. Se as consultas cruzam coleções o tempo todo, o modelo relacional provavelmente era o certo.
E vale repetir: Postgres com jsonb dá flexibilidade de documento, índices GIN sobre o JSON, e transação ACID multi-tabela. "Preciso de schema flexível" não implica necessariamente trocar de banco.
Exemplo prático
Um catálogo de produtos em que cada categoria tem atributos diferentes — camiseta tem tamanho e cor, notebook tem processador e memória.
No modelo relacional, isso vira uma tabela de atributos genéricos (EAV) com consultas desconfortáveis, ou uma tabela por categoria. No modelo de documento, cada produto simplesmente carrega seus campos.
O produto inteiro é lido numa operação, com variantes e imagens embutidas. A consulta por atributo ({"cor": "azul"}) funciona com um índice.
O limite aparece quando surge a pergunta "quantos produtos foram vendidos por categoria no último trimestre" — agregação analítica cruzando coleções. Aí o caminho é replicar para um banco analítico, não forçar o documento.
Relacionado
Parte de Databases · roadmap.sh/system-design