Amazon DynamoDB explicado: construindo sistemas escaláveis
Aprenda o que é o Amazon DynamoDB, como seu modelo NoSQL funciona e padrões práticos de design para sistemas escaláveis e de baixa latência.

O que é o DynamoDB e por que equipes o usam
Amazon DynamoDB é um serviço de banco de dados NoSQL totalmente gerenciado da AWS, projetado para aplicações que precisam de leituras e gravações com latência consistentemente baixa em praticamente qualquer escala. “Totalmente gerenciado” significa que a AWS cuida do trabalho de infraestrutura — provisionamento de hardware, replicação, patching e muitas tarefas operacionais — para que as equipes possam focar em entregar funcionalidades em vez de administrar servidores de banco de dados.
No núcleo, o DynamoDB armazena dados como itens (linhas) dentro de tabelas, mas cada item pode ter atributos flexíveis. O modelo de dados é melhor entendido como uma mistura de:
- Key-value: buscar um item rapidamente pela sua chave primária, como procurar um registro por ID.
- Documento: armazenar atributos aninhados (maps e lists), semelhante a JSON, útil para campos relacionados sem um esquema rígido.
Equipes escolhem DynamoDB quando querem performance previsível e operações mais simples para cargas que não se ajustam bem a joins relacionais. É comumente usado em microsserviços (cada serviço tendo seus próprios dados), apps serverless com tráfego em rajadas e sistemas orientados a eventos que reagem a mudanças nos dados.
Este post percorre os blocos de construção (tabelas, chaves e índices), como modelar em torno de padrões de acesso (incluindo design de tabela única), como funcionam escalabilidade e modos de capacidade, e padrões práticos para transmitir mudanças a uma arquitetura orientada a eventos.
Conceitos Centrais: Tabelas, Itens e Chaves Primárias
DynamoDB é organizado em torno de alguns blocos simples, mas os detalhes importam porque determinam como você modela dados e quão rápidas (e custo-efetivas) serão as requisições.
Tabelas, itens e atributos
Uma tabela é o container de nível superior. Cada registro na tabela é um item (semelhante a uma linha), e cada item é um conjunto de atributos (semelhante a colunas).
Ao contrário de bancos relacionais, itens na mesma tabela não precisam compartilhar os mesmos atributos. Um item pode ter {status, total, customerId}, enquanto outro inclui {status, shipmentTracking} — o DynamoDB não exige um esquema fixo.
Chaves primárias: simples vs. composta
Todo item é identificado de forma única por uma chave primária, e o DynamoDB suporta dois tipos:
- Chave primária simples (apenas chave de partição): um atributo identifica unicamente cada item.
- Chave primária composta (chave de partição + chave de ordenação): múltiplos itens podem compartilhar a mesma chave de partição, enquanto a chave de ordenação os distingue e define a ordem dentro dessa partição.
Na prática, chaves compostas permitem padrões de acesso “agrupados”, como “todos os pedidos de um cliente, do mais novo para o mais antigo”.
Query vs scan (visão geral)
Um Query lê itens por chave primária (ou pela chave de um índice). Ele mira uma chave de partição específica e pode filtrar por intervalos na chave de ordenação — este é o caminho eficiente e preferido.
Um Scan percorre toda a tabela (ou índice) e depois aplica filtros. É fácil começar com ele, mas costuma ser mais lento e mais caro em escala.
Limites a ter em mente
Algumas restrições que você encontrará cedo:
- Tamanho máximo de item: 400 KB.
- Tipos de atributo: escalares (string/number/binary/boolean/null), sets, lists e maps.
- Atributos de chave devem ser escalares (não é permitido usar lists/maps como chave de partição ou de ordenação).
Esses fundamentos fundamentam tudo o que vem a seguir: padrões de acesso, escolhas de índices e características de performance.
Modelo de Dados do DynamoDB: Key-Value e Documento
DynamoDB costuma ser descrito tanto como um armazenamento key-value quanto como um banco de documentos. Isso é preciso, mas ajuda entender o que cada lado implica no design do dia a dia.
Acesso key-value vs. itens estilo documento
No cerne, você recupera dados por chave. Forneça os valores da chave primária e o DynamoDB retorna um único item. Essa busca por chave é o que entrega armazenamento de baixa latência e previsível para muitas cargas.
Ao mesmo tempo, um item pode conter atributos aninhados (maps e lists), o que o faz se comportar como um banco de documentos: você pode armazenar payloads estruturados sem definir um esquema rígido previamente.
Modelando estruturas hierárquicas estilo JSON em itens
Itens mapeiam naturalmente para dados tipo JSON:
- Maps representam objetos (ex.:
profile.name,profile.address). - Lists representam arrays (ex.: ações recentes, tags).
Isso é ideal quando uma entidade é normalmente lida inteira — como um perfil de usuário, um carrinho de compras ou um bundle de configuração.
Quando desnormalizar (e por que é comum)
DynamoDB não oferece joins no servidor. Se seu app precisa buscar “um pedido mais seus itens de linha mais o status de envio” em um único caminho de leitura, você frequentemente desnormaliza: copia alguns atributos em múltiplos itens ou incorpora subestruturas pequenas diretamente dentro do item.
Trade-offs vs. normalização relacional
Desnormalizar aumenta a complexidade de escrita e pode criar fan-out nas atualizações. O ganho é reduzir round trips e acelerar leituras — muitas vezes a diferença crítica em sistemas escaláveis.
Chave de Partição e Chave de Ordenação: projetando para padrões de acesso
As consultas mais rápidas no DynamoDB são as que você pode expressar como “me dê esta partição” (e opcionalmente “dentro desta partição, me dê este intervalo”). Por isso a escolha da chave é sobre como você lê, não apenas como armazena.
Chave de partição: distribuição e leituras previsíveis
A chave de partição determina qual partição física armazena um item. O DynamoDB faz hash desse valor para espalhar dados e tráfego. Se muitas requisições se concentrarem em um pequeno conjunto de valores de chave de partição, você pode criar partições “quentes” e atingir limites de throughput mesmo que a tabela esteja majoritariamente ociosa.
Boas chaves de partição:
- Têm alta cardinalidade (muitos valores distintos)
- Correspondem a um padrão de acesso frequente (para que leituras sejam diretas, não filtradas)
- Evitam valores que se tornam “populares” (ex.: uma constante como
"GLOBAL")
Chave de ordenação: consultas por intervalo e entidades agrupadas
Com uma chave de ordenação, itens que compartilham a mesma chave de partição são armazenados juntos e ordenados pela chave de ordenação. Isso habilita eficientemente:
- Consultas por intervalo (
BETWEEN,begins_with) - Leituras ordenadas por tempo (mais recentes primeiro com scans invertidos)
- Agrupamento de entidades (múltiplos tipos de item sob uma mesma chave de partição)
Um padrão comum é compor a chave de ordenação, como TYPE#id ou TS#2025-12-22T10:00:00Z, para suportar diversos formatos de consulta sem tabelas extras.
Mapeando padrões de acesso às chaves
- Buscar por ID:
PK = USER#<id>(simplesGetItem) - Listar por usuário:
PK = USER#<id>,SK begins_with ORDER#(ouSK = CREATED_AT#...) - Séries temporais:
PK = DEVICE#<id>,SK = TS#<timestamp>comBETWEENpara janelas de tempo
Como a escolha de chaves afeta performance e escalabilidade
Se sua chave de partição alinha com suas consultas de maior volume e distribui uniformemente, você terá leituras e gravações com latência consistentemente baixa. Se não alinhar, você compensará com scans, filtros ou índices extras — cada um aumentando custo e risco de hot keys.
Índices Secundários: GSI e LSI explicados
Índices secundários dão ao DynamoDB caminhos alternativos de consulta além da chave primária da tabela. Em vez de remodelar a tabela base sempre que surge um novo padrão de acesso, você pode adicionar um índice que re-chaveia os mesmos itens para uma consulta diferente.
GSI vs. LSI: qual a diferença?
Um Global Secondary Index (GSI) tem sua própria chave de partição (e chave de ordenação opcional) que pode ser completamente diferente da tabela. É “global” porque cobre todas as partições da tabela e pode ser adicionado ou removido a qualquer momento. Use um GSI quando precisar de um novo padrão de acesso que não cabe na chave original — por exemplo, consultar pedidos por customerId quando a tabela é keyeada por orderId.
Um Local Secondary Index (LSI) compartilha a mesma chave de partição da tabela base, mas usa uma chave de ordenação diferente. LSIs devem ser definidos na criação da tabela. Eles são úteis quando você quer múltiplas ordenações dentro do mesmo grupo de entidade (mesma chave de partição), como buscar pedidos de um cliente ordenados por createdAt ou por status.
Projeções: o que é copiado para o índice
A projeção determina quais atributos o DynamoDB armazena no índice:
- KEYS_ONLY: armazenamento mais barato, mas você frequentemente precisará de uma leitura extra na tabela base.
- INCLUDE: copia apenas os atributos que você retorna com frequência.
- ALL: mais simples, mas pode inflar storage e custo das escritas.
Amplificação de escrita (o custo oculto)
Cada escrita na tabela base pode acionar escritas em um ou mais índices. Mais GSIs e projeções amplas aumentam o custo de escrita e o consumo de capacidade. Planeje índices em torno de padrões estáveis e mantenha atributos projetados no mínimo necessário quando possível.
Modos de Capacidade e Comportamento de Escala
A escalabilidade do DynamoDB começa com uma escolha: On-Demand ou Provisioned. Ambos podem alcançar throughput muito alto, mas se comportam de maneiras distintas sob tráfego variável.
On-Demand vs Provisioned: como escolher
On-Demand é o mais simples: você paga por requisição e o DynamoDB acomoda carga variável automaticamente. É adequado para tráfego imprevisível, produtos em estágio inicial e workloads em rajadas onde você não quer gerenciar metas de capacidade.
Provisioned é planejamento de capacidade: você especifica throughput de leitura e gravação (ou usa auto scaling) e obtém precificação mais previsível em uso estável. Costuma sair mais barato para workloads consistentes e equipes que conseguem prever demanda.
Capacidade de leitura/escrita na prática
Throughput provisionado é medido em:
- RCUs (Read Capacity Units): aproximadamente uma leitura fortemente consistente por segundo para até 4 KB (ou duas leituras eventualmente consistentes).
- WCUs (Write Capacity Units): aproximadamente uma escrita por segundo para até 1 KB.
O tamanho do item e o padrão de acesso determinam o custo real: itens maiores, consistência forte e scans podem consumir capacidade rapidamente.
Noções básicas de auto scaling (e limites)
O auto scaling ajusta RCUs/WCUs provisionados com base em metas de utilização. Ajuda em crescimento gradual e ciclos previsíveis, mas não é instantâneo. Picos súbitos ainda podem causar throttling se a capacidade não subir rápido o suficiente, e não resolve uma chave de partição quente que concentra tráfego.
DAX: cache para workloads de leitura intensiva
DynamoDB Accelerator (DAX) é um cache em memória que pode reduzir latência de leitura e descarregar leituras repetidas (ex.: páginas de produto populares, sessões). É mais útil quando muitos clientes solicitam repetidamente os mesmos itens; não ajuda padrões com muitas escritas e não substitui um bom design de chaves.
Consistência, Transações e Correção
O DynamoDB permite que você troque garantias de leitura por latência e custo, então é importante ser explícito sobre o que “correto” significa para cada operação.
Leituras eventualmente consistentes vs fortemente consistentes
Por padrão, GetItem e Query usam leituras eventualmente consistentes: você pode, brevemente, ver um valor mais antigo logo após uma escrita. Isso costuma ser aceitável para feeds, catálogos de produtos e outras visões read-mostly.
Com leituras fortemente consistentes (opção para leituras na tabela base em uma única região), o DynamoDB garante que você verá a última escrita confirmada. Consistência forte custa mais capacidade de leitura e pode aumentar a latência em cauda, então reserve para leituras realmente críticas.
Quando a consistência forte importa
Consistência forte é valiosa para leituras que gateiam ações irreversíveis:
- Checar inventário disponível antes de confirmar um pedido
- Ler uma flag de autorização antes de conceder acesso
- Buscar o estado atual de um workflow antes de executar o próximo passo
Para contadores, a abordagem mais segura normalmente não é “ler forte e depois escrever”, mas uma atualização atômica (ex.: UpdateItem com ADD) para que incrementos não se percam.
Leituras/escritas transacionais
Transações do DynamoDB (TransactWriteItems, TransactGetItems) oferecem semântica ACID para até 25 itens. São úteis quando você precisa atualizar vários itens juntos — como criar um pedido e reservar inventário — ou impor invariantes que não toleram estados intermediários.
Idempotência para retries seguros
Retries são normais em sistemas distribuídos. Faça escritas idempotentes para que retries não dupliquem efeitos:
- Use um token de requisição do cliente (chave de idempotência) armazenado com o resultado
- Enforce unicidade com
ConditionExpression(ex.: "only create if attribute_not_exists") - Prefira atualizações atômicas em vez de ciclos ler-modificar-escrever
Correção no DynamoDB é, em grande parte, escolher o nível certo de consistência e projetar operações para que retries não quebrem os dados.
Partições, Hot Keys e Picos de Tráfego
DynamoDB armazena dados de tabela em múltiplas partições físicas. Cada partição tem throughput finito para leituras e escritas, além de limite no quanto de dados pode armazenar. Sua chave de partição determina onde um item vive; se muitas requisições mirarem o mesmo valor de chave de partição (ou um pequeno conjunto), essa partição vira o gargalo.
Por que partições quentes acontecem
Partições quentes geralmente são causadas por escolhas de chave que concentram tráfego: uma chave “global” como USER#1, TENANT#default ou STATUS#OPEN, ou padrões ordenados por tempo onde todos gravam em “agora” sob uma mesma chave.
Sintomas de chaves quentes e tráfego desigual
Normalmente você verá:
- Throttling (
ProvisionedThroughputExceededException) para um subconjunto de chaves - Latência elevada e espigada para alguns padrões de acesso enquanto outros permanecem rápidos
- Métricas no CloudWatch mostrando capacidade consumida desigual e picos súbitos
Técnicas de mitigação
Projete para distribuição primeiro, depois para conveniência de consulta:
- Design de chave: garanta chaves de partição de alta cardinalidade (ex.:
TENANT#<id>em vez de uma constante compartilhada). - Sharding de escrita: adicione um pequeno sufixo/prefixo aleatório ou hasheado como
ORDER#<id>#<shard>para espalhar escritas por N shards e depois consulte através dos shards quando necessário. - Buckets por tempo: agrupe por hora/dia (
METRIC#2025-12-22T10) para evitar “todas as escritas indo para o item mais recente”.
Lidando com workloads em rajadas
Para picos imprevisíveis, On-Demand pode absorver rajadas (dentro dos limites do serviço). No modo Provisioned, use auto scaling e implemente backoff exponencial com jitter nos clientes ao enfrentar throttles para evitar retries sincronizados que amplifiquem o pico.
Padrões de Modelagem de Dados para Sistemas Escaláveis
A modelagem no DynamoDB começa por padrões de acesso, não por diagramas ER. Você projeta chaves para que as consultas necessárias se tornem operações rápidas de Query, enquanto o restante é evitado ou tratado assincronamente.
Design de tabela única (e por que equipes gostam)
“Design de tabela única” significa armazenar vários tipos de entidade (usuários, pedidos, mensagens) em uma única tabela e usar convenções de chave consistentes para buscar dados relacionados em um único Query. Isso reduz round-trips entre entidades e mantém a latência previsível.
Uma abordagem comum é usar chaves compostas:
PKagrupa uma partição lógica (ex.:USER#123)SKordena itens dentro desse grupo (ex.:PROFILE,ORDER#2025-12-01,MSG#000123)
Isso permite buscar “tudo de um usuário” ou “apenas pedidos de um usuário” escolhendo um prefixo de chave de ordenação.
Relacionamentos: listas de adjacência e muitos-para-muitos
Para relacionamentos tipo grafo, uma adjacency list funciona bem: armazene arestas como itens.
PK = USER#123,SK = FOLLOWS#USER#456
Para suportar consultas reversas ou verdadeiros muitos-para-muitos, adicione um item de aresta invertida ou projete um GSI, dependendo dos caminhos de leitura.
Séries temporais: bucket + sort key + TTL
Para eventos e métricas, evite partições sem limite usando bucketização:
PK = DEVICE#9#2025-12-22(device + dia)SK = TS#1734825600(timestamp)
Use TTL para expirar pontos antigos automaticamente, e mantenha agregados (rollups horários/diários) como itens separados para dashboards rápidos.
Se quiser um aprofundamento nas convenções de chave, veja /blog/partition-key-and-sort-key-design.
Streams e Arquiteturas Orientadas a Eventos
DynamoDB Streams é o mecanismo built-in de captura de mudanças (CDC). Quando habilitado em uma tabela, todo insert, update ou delete gera um registro de stream que consumidores downstream podem reagir — sem precisar poll da tabela.
Fundamentos do DynamoDB Streams
Um registro de stream contém chaves e (opcionalmente) a imagem antiga e/ou nova do item, dependendo do stream view type escolhido (keys only, new image, old image, both). Registros são agrupados em shards, que você lê de forma sequencial.
Construindo workflows orientados a eventos
Uma arquitetura comum é DynamoDB Streams → AWS Lambda, onde cada lote de registros aciona uma função. Outros consumidores também são possíveis (consumidores customizados, ou enviar para sistemas de analytics/log).
Workflows típicos incluem:
- Views materializadas: escrever uma tabela de leitura desnormalizada quando a tabela fonte muda.
- Invalidação de cache: expirar ou atualizar itens em Redis/ElastiCache após gravações.
- Logs de auditoria: anexar eventos imutáveis de mudança a uma tabela de auditoria ou a um armazenamento externo.
Isso mantém a tabela primária otimizada para leituras/escritas de baixa latência enquanto empurra trabalho derivado para consumidores assíncronos.
Ordenação, retries e correção
Streams fornecem processamento ordenado por shard (o que tipicamente se correlaciona com a chave de partição), mas não há ordenação global entre todas as chaves. A entrega é at-least-once, então duplicatas podem ocorrer.
Para lidar com isso com segurança:
- Faça handlers idempotentes (ex.: upsert por chave primária, usar escritas condicionais ou armazenar IDs de evento processados).
- Espere retries e falhas parciais de lote; use DLQs/destinos de falha quando possível.
- Mantenha efeitos colaterais (emails, pagamentos) protegidos por deduplicação ou salvaguardas transacionais.
Projetado com essas garantias em mente, Streams pode transformar o DynamoDB em uma espinha dorsal sólida para sistemas orientados a eventos.
Confiabilidade, Backups e Observabilidade
DynamoDB é projetado para alta disponibilidade espalhando dados por múltiplas Availability Zones dentro de uma região. Para a maioria das equipes, os ganhos práticos de confiabilidade vêm de uma estratégia clara de backup, entender opções de replicação e monitorar as métricas certas.
Backups: on-demand vs point-in-time recovery
Backups on-demand são snapshots manuais (ou automatizados) que você tira quando quer um ponto de restauração conhecido — antes de uma migração, após um release ou antes de um grande backfill. São ótimos para “marcar” momentos.
Point-in-time recovery (PITR) captura mudanças continuamente para que você possa restaurar a tabela para qualquer segundo dentro da janela de retenção. PITR é a rede de segurança para deletes acidentais, deploys ruins ou escritas malformadas.
Replicação e opções multi-região
Se precisar de resiliência multi-região ou leituras com baixa latência próximas aos usuários, Global Tables replicam dados entre regiões selecionadas. Elas simplificam planos de failover, mas introduzem delays de replicação cross-region e considerações de resolução de conflitos — mantenha claros padrões de escrita e propriedade de itens.
Monitoramento essencial
No mínimo, alerte sobre:
- Latência (p95/p99) para leituras e gravações
- Requests throttled e erros do sistema
- Consumed capacity (e folga versus o provisionado)
Esses sinais normalmente indicam problemas com partições quentes, capacidade insuficiente ou padrões de acesso inesperados.
Playbooks de incidente
Para throttling, primeiro identifique o padrão de acesso que o causa, então mitigue trocando temporariamente para on-demand ou aumentando a capacidade provisionada, e considere shardear chaves quentes.
Para outages parciais ou aumento de erros, reduza o raio de ação: desative tráfego não crítico, faça retries com backoff+jitter e degrade graciosamente (por exemplo, servir leituras em cache) até a tabela se estabilizar.
Segurança e Controle de Acesso
A segurança no DynamoDB trata majoritariamente de restringir quem pode chamar quais ações de API, de onde e em quais chaves. Como tabelas podem conter muitos tipos de entidade (e às vezes múltiplos tenants), controle de acesso deve ser projetado junto com o modelo de dados.
Permissões IAM: privilégio mínimo por padrão
Comece com políticas IAM baseadas em identidade que limitem ações (ex.: dynamodb:GetItem, Query, PutItem) ao mínimo necessário e escopo para ARNs de tabela específicos.
Para controle mais fino, use dynamodb:LeadingKeys para restringir acesso por valores de chave de partição — útil quando um serviço ou tenant só deve ler/escrever itens no seu próprio keyspace.
Criptografia: o que verificar
DynamoDB criptografa dados em repouso por padrão usando chaves AWS owned ou uma KMS key gerenciada pelo cliente. Se você tem requisitos de compliance, verifique:
- A tabela está configurada com a KMS key pretendida
- A role que chama tem as permissões KMS necessárias (e nada a mais)
Para criptografia em trânsito, garanta que os clientes usem HTTPS (SDKs AWS fazem isso por padrão). Se você termina TLS em um proxy, confirme que o salto entre o proxy e o DynamoDB ainda esteja criptografado.
Controles de rede: reduzir caminhos de exfiltração
Use um VPC Gateway Endpoint para DynamoDB para que o tráfego permaneça na rede AWS e você possa aplicar políticas de endpoint para restringir acesso. Combine isso com controles de egress (NACLs, security groups e roteamento) para evitar caminhos que permitam acesso público irrestrito.
Design multi-tenant e padrões de isolamento
Para tabelas compartilhadas, inclua um identificador de tenant na chave de partição (por exemplo, TENANT#<id>), e então faça enforcement de isolamento de tenant com condições IAM em dynamodb:LeadingKeys.
Se precisar de isolamento mais forte, considere tabelas separadas por tenant ou por ambiente, e reserve design de tabela compartilhada quando simplicidade operacional e eficiência de custo compensarem um raio de blast maior.
Otimização de Custos para DynamoDB
DynamoDB costuma ser “barato quando você é preciso, caro quando é vago.” Custos seguem seus padrões de acesso, então o melhor trabalho de otimização começa por tornar esses padrões explícitos.
Entenda os direcionadores de custo
Sua fatura é moldada principalmente por:
- Leituras e gravações (RCUs/WCUs no modo provisionado, unidades por requisição no on-demand)
- Armazenamento (dados da tabela e tamanho dos itens)
- Índices secundários (cada GSI tem seus próprios custos de gravação e armazenamento)
- Streams (leituras contra registros de stream e consumidores downstream)
Uma surpresa comum: cada escrita na tabela é também uma escrita em cada GSI afetado, então “só mais um índice” pode multiplicar o custo de escrita.
Projetar chaves para evitar desperdício
Bom design de chaves reduz a necessidade de operações caras. Se você frequentemente precisa de Scan, está pagando para ler dados que serão descartados.
Prefira:
Querypor partition key (e opcionalmente condições na sort key)- Projeções estreitas nos seus GSIs (projetar apenas atributos realmente necessários)
Se um padrão de acesso é raro, considere servi-lo via tabela separada, job ETL ou um modelo de leitura em cache em vez de um GSI permanente.
Controlar armazenamento com TTL e lifecycle
Use TTL para deletar automaticamente itens de curta duração (sessions, tokens temporários, estados intermediários). Isso reduz armazenamento e pode manter índices menores ao longo do tempo.
Para dados append-heavy (eventos, logs), combine TTL com designs de sort-key que permitam consultar “apenas recentes”, evitando tocar histórico frio rotineiramente.
Right-size de capacidade e evitar picos acidentais
No modo provisionado, defina bases conservadoras e escale com auto scaling baseado em métricas reais. No modo on-demand, aten atenção a padrões ineficientes (itens grandes, clientes chatos) que disparam volume de requisições.
trate Scan como último recurso — quando precisar processar a tabela inteira, agende fora de pico ou execute como batch controlado com paginação e backoff.
Quando Escolher o DynamoDB (e Quando Não)
DynamoDB brilha quando sua aplicação pode ser expressa como um conjunto de padrões de acesso bem definidos e você precisa de latência consistentemente baixa em alta escala. Se você consegue descrever suas leituras e gravações antecipadamente (por chave de partição, chave de ordenação e poucos índices), muitas vezes é uma das formas mais simples de operar um datastore altamente disponível.
Casos ideais
DynamoDB é uma escolha forte quando você tem:
- Consultas previsíveis (buscar perfil do usuário, listar pedidos de um usuário por tempo, carregar sessão por ID)
- Alto throughput de escrita ou tráfego com picos que você não quer gerenciar
- Necessidade de escalonamento horizontal sem gerenciar servidores
- Designs orientados a eventos usando Streams para acionar trabalhos downstream
Quando considerar alternativas
Procure outras opções se seus requisitos centrais incluírem:
- Joins complexos entre muitas entidades ou travessia frequente de relacionamentos
- Consultas ad hoc e análises que mudam semanalmente (group-bys, filtros exploratórios)
- Busca textual pesada e ranking de relevância sem um índice externo
Abordagens híbridas que funcionam bem
Muitas equipes mantêm DynamoDB para leituras/escritas “quentes” e adicionam:
- S3 + Athena para analytics e relatórios históricos
- OpenSearch (ou similar) para busca full-text e faceting
- Uma camada de cache quando certas chaves são extremamente lidas
Nota sobre prototipagem: encurte o caminho do modelo para o app
Se você está validando padrões de acesso e convenções de tabela única, rapidez importa. Equipes às vezes prototipam o serviço e UI em Koder.ai (uma plataforma que gera apps web, server e mobile a partir de chat) e então iteram no design de chaves do DynamoDB à medida que caminhos de consulta reais emergem. Mesmo que o backend de produção difira, protótipos de ponta a ponta ajudam a revelar quais queries deveriam ser Query e quais se tornariam scans caros.
Checklist rápido de decisão
Valide: (1) suas queries principais são conhecidas e baseadas em chaves, (2) necessidades de correção batem com o modelo de consistência, (3) tamanhos esperados de itens e crescimento estão entendidos, e (4) o modelo de custo (on-demand vs provisionado + autoscaling) cabe no orçamento.
Perguntas frequentes
O que é o DynamoDB e quando é uma boa escolha?
DynamoDB é um banco de dados NoSQL totalmente gerenciado da AWS, projetado para leituras/gravações com latência consistentemente baixa em escalas muito altas. Equipes o adotam quando conseguem definir padrões de acesso baseados em chaves (buscar por ID, listar por proprietário, consultas por intervalo de tempo) e querem evitar operar a infraestrutura do banco de dados.
É especialmente comum em microsserviços, aplicações serverless e sistemas orientados a eventos.
O que são tabelas, itens e atributos no DynamoDB?
Uma tabela guarda itens (como linhas). Cada item é um conjunto flexível de atributos (como colunas) e pode incluir dados aninhados.
O DynamoDB funciona bem quando uma requisição normalmente precisa “da entidade inteira”, porque itens podem conter maps e lists (estruturas tipo JSON).
Qual a diferença entre chave primária simples e chave primária composta?
Uma chave de partição sozinha identifica um item (chave primária simples). Uma chave composta (chave de partição + chave de ordenação) permite que múltiplos itens compartilhem a mesma chave de partição, sendo unicamente identificados e ordenados pela chave de ordenação.
Chaves compostas habilitam padrões como:
- “Todos os pedidos de um cliente”
- “Eventos de um dispositivo entre timestamps”
Quando devo usar Query vs Scan?
Use Query quando você puder especificar a chave de partição (e opcionalmente uma condição na chave de ordenação). É o caminho rápido e escalável.
Use Scan apenas quando precisar realmente ler tudo; ele percorre toda a tabela ou índice e filtra depois, o que costuma ser mais lento e caro.
Se você estiver fazendo muitos scans, é sinal de que o design de chave ou índice precisa ser revisado.
O que são GSI e LSI, e como escolher?
Índices secundários dão caminhos alternativos de consulta.
- GSI (Global Secondary Index): pode usar uma chave de partição diferente (e opcionalmente uma chave de ordenação) da tabela base; pode ser adicionado depois.
- LSI (Local Secondary Index): compartilha a mesma chave de partição da tabela base, mas usa uma chave de ordenação diferente; deve ser definido na criação da tabela.
Índices aumentam o custo das escritas porque cada escrita na tabela base é replicada nos índices afetados.
Como escolher entre capacidade On-Demand e Provisioned?
Escolha On-Demand se o tráfego for imprevisível, com picos, ou se você não quer gerenciar capacidade. Você paga por requisição.
Escolha Provisioned se o uso for estável/preditível e você quiser custos mais controlados. Combine com auto scaling, lembrando que ele pode não reagir instantaneamente a picos súbitos.
Quais opções de consistência o DynamoDB oferece, e quando elas importam?
Por padrão, leituras são eventualmente consistentes, o que significa que você pode ver um valor antigo logo após uma escrita.
Use leituras fortemente consistentes (quando disponíveis) para verificações críticas que precisam estar atualizadas, como gates de autorização ou estados de workflow.
Para correção sob concorrência, prefira atualizações atômicas (ex.: escritas condicionais ou ADD) em vez de ciclos ler-modificar-escrever.
Quando devo usar transações no DynamoDB?
Transações (TransactWriteItems, TransactGetItems) fornecem garantias ACID para até 25 itens.
Use-as quando for necessário atualizar múltiplos itens juntos (ex.: criar um pedido e reservar inventário) ou garantir invariantes que não toleram estados parciais.
Elas custam mais e adicionam latência, então reserve para fluxos que realmente exijam essas garantias.
O que são hot keys/partições e como evitá-las?
Partições quentes ocorrem quando muitas requisições atingem o mesmo valor de chave de partição (ou um pequeno conjunto de valores), causando throttling mesmo que a tabela esteja ociosa no geral.
Mitigações comuns:
- Escolher chaves de partição com alta cardinalidade
- Implementar sharding de escrita (sufixo/prefixo aleatório ou hash)
- Usar buckets por tempo para dados time-series
- Implementar backoff exponencial com jitter em clientes ao receber throttles
Como os DynamoDB Streams suportam arquiteturas orientadas a eventos?
Habilite DynamoDB Streams para obter um fluxo de mudanças em inserts, updates e deletes. Um padrão comum é Streams → Lambda para acionar trabalhos downstream.
Garantias importantes para projetar:
- Ordenação é por shard (não global)
- Entrega é at-least-once (podem ocorrer duplicatas)
Faça os consumidores idempotentes (upsert por chave, escritas condicionais, ou controle de IDs de evento processados).