Quando NÃO Usar Single-Table Design no DynamoDB
Single-table design é o conselho padrão para DynamoDB, e ele merece: um Query devolve
um pai e seus filhos, sem joins, sem N+1.
Mas é uma troca — você compra velocidade de leitura com um schema rígido e opaco. Algumas cargas de trabalho não podem pagar esse preço, e forçar uma tabela nelas é sua própria cilada.
Quando não usar single-table design no DynamoDB?
Evite single-table design quando sua carga de trabalho for de analytics OLAP pesado, CRUD simples com poucas entidades não relacionadas, ou entidades que escalam e falham de forma independente. Nesses casos, múltiplas tabelas leem melhor, custam o mesmo e ficam mais flexíveis. Single-table design só vence quando os padrões de acesso são conhecidos, relacionados e de alto volume.
- Analytics pesado? Não use single-table. Chaves sobrecarregadas são hostis ao OLAP — exporte para um armazenamento colunar e consulte lá.
- CRUD simples com um punhado de padrões de acesso? Uma tabela por entidade está ótimo, legível, e não te custa nada em performance.
- Entidades que escalam ou falham independentemente? Tabelas separadas te deixam ajustar, cobrar e isolar o raio de explosão de cada uma por conta própria.
- Single-table ainda vence quando seus padrões são conhecidos, relacionados e de alto volume — esse é o caso para o qual foi feito.
Saiba o que single-table de fato custa
Single-table design não é grátis; ele só move o custo para fora do caminho de leitura e para todo o resto. Você paga em legibilidade e flexibilidade.
Uma tabela contendo cinco tipos de entidade por trás de PK/SK é difícil de ler,
difícil de fazer onboarding e difícil de mudar. Um novo padrão de acesso pode significar
um backfill em todo tipo de item da partição.
Então a pergunta não é "single-table é bom?". É "meus padrões de acesso justificam a rigidez?". Quando não justificam, recorra a múltiplas tabelas.
Não faça single-table de uma carga de analytics
O DynamoDB é feito para OLTP — leituras pequenas, conhecidas, point-and-range. Analytics
é OLAP: GROUP BY, grandes agregações, fatiamento ad-hoc em todo o dataset. Os dois
puxam em direções opostas.
Single-table design piora o OLAP, não melhora. Chaves sobrecarregadas e tipos de entidade misturados significam que um job de analytics precisa primeiro desembaraçar qual item é qual antes de poder somar qualquer coisa — o oposto de um scan colunar limpo.
Vindo do SQL, o reflexo é escrever a agregação contra a tabela ativa. No DynamoDB isso é
um Scan completo — você paga por e lê todo item, que é a
cilada do Scan em volume total.
A correção não é uma chave mais esperta. É um armazenamento diferente. A própria orientação da AWS é exportar o DynamoDB para o S3 e rodar analytics com um engine de consulta como o Athena.
Mantenha OLTP e OLAP em engines separados (AWS DynamoDB Developer Guide,
S3DataExport.html).
Não faça single-table de CRUD simples
Se o seu app lê e escreve algumas entidades não relacionadas pelo próprio id, e você tem talvez três padrões de acesso, single-table não te compra nada.
Pegue uma tabela Tenants e uma tabela ApiKeys para uma pequena ferramenta B2B:
| TenantId | Name | PlanTier |
|---|---|---|
| TNT-8842 | Northwind | pro |
| KeyId | TenantId | Scope |
|---|---|---|
| KEY-01H9... | TNT-8842 | read-write |
Cada consulta é um GetItem por id, ou um Query em um GSI chaveado por TenantId.
Não há busca de pai-e-filhos para otimizar, então não há nada para uma partição
sobrecarregada ganhar. Duas tabelas claras leem melhor do que uma turva.
A cilada é fazer cargo cult de single-table porque é "boa prática". A boa prática é padrão-de-acesso-primeiro. Se os padrões são triviais, a forma simples é a forma certa.
Separe tabelas que escalam ou falham independentemente
Uma única tabela compartilha uma superfície de throughput, um backup, um raio de explosão. Quando duas entidades têm taxas de escrita ou necessidades de durabilidade muito diferentes, esse destino compartilhado vira uma desvantagem.
Imagine um sistema de rastreamento de frota. Veículos mudam raramente; sua telemetria despeja a cada segundo:
| VehicleId | Make | Model | Region |
|---|---|---|---|
| VEH-204 | Volvo | FH16 | eu-west |
| DeviceTs | VehicleId | SpeedKph | Fuel |
|---|---|---|---|
| 2026-06-23T10:00:01Z | VEH-204 | 88 | 0.61 |
Duas tabelas te deixam provisionar a telemetria para uma mangueira de incêndio, manter os veículos minúsculos e baratos, definir um TTL só na telemetria, e impedir que uma tempestade de escrita de telemetria cause throttling nas leituras do catálogo de veículos. Uma tabela acopla tudo isso.
Conforme o paper Amazon Dynamo de 2007, particionamento e disponibilidade são preocupações de primeira classe — tabelas independentes te dão controle independente sobre ambos.
Mapeie a decisão antes de comprometer
Passe a carga por um único portão: as entidades são relacionadas, e os padrões são conhecidos e de alto volume? Se não, múltiplas tabelas.
Eis a decisão como um fluxo — comece no topo e siga o primeiro ramo que corresponder:
Só a folha do canto inferior direito merece single-table; todo outro caminho é melhor servido por mais de uma tabela.
Single vs múltiplas, frente a frente
| Fator | Single-table | Múltiplas tabelas |
|---|---|---|
| Leituras relacionadas | Um Query, sem joins | Join no cliente ou idas e voltas extras |
| Legibilidade | Chaves sobrecarregadas opacas | Uma entidade por tabela, autodocumentada |
| Novo padrão de acesso | Muitas vezes um backfill | Adicione uma tabela ou GSI isoladamente |
| Analytics / OLAP | Hostil — desembaraçar antes de agregar | Ainda exporta, mas mais limpo por entidade |
| Escalonamento independente | Throughput + raio de explosão compartilhados | Ajuste, cobre, TTL e backup separadamente |
| Melhor quando | Padrões conhecidos, relacionados, de alto volume | Não relacionados, em evolução ou analíticos |
Ciladas + próximos passos
O erro espelhado é supercorrigir — dividir entidades genuinamente relacionadas e de alto volume em uma tabela por entidade e reconstruir joins estilo SQL no seu app. Essa é a cilada do N+1 que o single-table mata.
Escolha a forma que os padrões de acesso pedem, não o dogma.
Quando você for modelar relacionamentos, apoie-se no tipo de índice certo — veja GSI vs LSI antes de adicionar um.
Quando você for escrever uma consulta contra um schema multi-tabela, esboce a
KeyConditionExpression no
DynamoDB Expression Builder primeiro.
Assim você pega uma forma de Scan completo antes que ela chegue à produção.
Depois experimente o DynoTable para navegar em ambas as formas contra suas próprias tabelas e ver qual delas seus padrões de acesso realmente querem.