Amazon DynamoDB é um banco de dados NoSQL totalmente gerenciado, orientado a chave-valor e documentos, com latência de milissegundos de forma consistente e capacidade de escalar horizontalmente para praticamente qualquer volume de tráfego, sem que você precise gerenciar servidores.
🎯 Para a certificação
Questões sobre DynamoDB testam se você entende como a partition key determina a distribuição física dos dados (e o risco de hot partitions), sabe escolher entre provisioned e on-demand capacity, distingue eventually consistent de strongly consistent reads, entende as diferenças reais entre GSI e LSI, e reconhece quando DynamoDB é a escolha certa em vez de RDS.
Resumo
Pense no DynamoDB como um sistema gigantesco de armários numerados, em vez de um arquivo com pastas hierárquicas como um banco relacional. Para guardar ou buscar algo, você não "procura na pasta certa" — você calcula diretamente o número do armário (a partition key), abre-o, e lá está o que você precisa, quase instantaneamente, não importa se existem 100 ou 100 bilhões de outros armários no prédio. O trade-off é que você precisa saber o número do armário (a chave) para ser rápido — buscar "todo mundo cujo sobrenome começa com S", sem saber o número exato, é lento e caro nesse modelo, ao contrário de um banco relacional otimizado para esse tipo de busca.
- Modelo de dados: chave-valor/documento, sem schema fixo por item (cada item pode ter atributos diferentes).
- Partition key: determina em qual partição física o item é armazenado — a escolha dessa chave é a decisão de modelagem mais importante do DynamoDB.
- Modos de capacidade: Provisioned (você define throughput fixo, com possibilidade de auto scaling) ou On-Demand (paga por requisição, sem gerenciar capacidade).
- Consistência: eventually consistent por padrão (mais barata, mais rápida); strongly consistent disponível opcionalmente para leituras que exigem o dado mais recente garantido.
1. Partition key e como os dados são distribuídos fisicamente
A partition key (também chamada de hash key) passa por uma função de hash internamente, e o resultado determina em qual partição física (um pedaço de infraestrutura de armazenamento, gerenciado internamente pela AWS) o item é guardado. Esse mecanismo é o que permite ao DynamoDB escalar horizontalmente de forma quase ilimitada — conforme o volume de dados/tráfego cresce, o serviço automaticamente cria mais partições e distribui os dados entre elas.
1.1 Hot partitions
Se a partition key escolhida tem baixa cardinalidade (poucos valores distintos) ou um padrão de acesso muito desbalanceado, uma quantidade desproporcional de tráfego acaba concentrada numa única partição física — isso é uma hot partition, e causa throttling e degradação de latência, mesmo que a capacidade total provisionada da tabela pareça suficiente no agregado.
Explicação didática: pense na partition key como o "endereço do bairro" onde o DynamoDB guarda seus dados internamente — cada valor único de chave tende a cair numa partição física diferente. Se você usar status = "ativo" como partition key para 1 milhão de usuários, quase todos os itens caem na mesma partição (mesmo "bairro"), sobrecarregando um único pedaço de hardware. A correção típica é usar uma chave de alta cardinalidade (ex: userId, que tem um valor único por usuário) ou, quando a chave naturalmente concentra tráfego (ex: um deviceId que gera volume desproporcional), adicionar um sufixo aleatório (write sharding) para espalhar artificialmente a carga entre múltiplas partições, remontando os dados na camada de aplicação quando necessário.
💡 Para a prova: "alto volume de escrita/leitura concentrado numa única chave" ou "throttling mesmo com capacidade agregada suficiente" quase sempre aponta para hot partition — a resposta correta envolve redesenhar a chave, não apenas aumentar capacidade provisionada.
2. Sort key e padrões de modelagem
A sort key (opcional) permite que múltiplos itens compartilhem a mesma partition key, mas sejam organizados e consultados por um segundo componente — formando o que se chama de chave composta (partition key + sort key).
Isso habilita padrões de modelagem muito usados na prova:
- Relação 1:N: ex:
PK = USER#123,SK = ORDER#<data>#<orderId>— todos os pedidos de um usuário compartilham a mesma partition key, e a sort key permite consultar por prefixo e ordenar por data automaticamente. - Consulta por prefixo/intervalo: operações como
begins_with,betweenna sort key permitem buscas eficientes sem escanear a tabela inteira (ex: "todos os pedidos de um usuário entre duas datas"). - Adjacency list: modelar relações complexas (muitos-para-muitos) armazenando "arestas" do grafo como itens dentro da mesma partição.
3. Modos de capacidade: Provisioned vs On-Demand
| Modo | Como funciona | Quando usar |
|---|---|---|
| Provisioned | Você define RCU/WCU (Read/Write Capacity Units) fixas, com opção de Auto Scaling ajustando dentro de limites configurados | Tráfego previsível ou com padrão conhecido; permite otimizar custo com planejamento |
| On-Demand | Cobrança por requisição real, sem definir capacidade antecipadamente; escala automaticamente para picos | Tráfego imprevisível, novas aplicações sem histórico de uso, picos abruptos difíceis de prever |
- RCU (Read Capacity Unit): 1 RCU = uma leitura fortemente consistente de até 4 KB por segundo (ou duas leituras eventualmente consistentes de até 4 KB, já que essas consomem metade do custo em RCU).
- WCU (Write Capacity Unit): 1 WCU = uma escrita de até 1 KB por segundo.
💡 Para a prova: se o cenário descreve uma aplicação nova, sem histórico de tráfego, ou com picos difíceis de prever (ex: uma campanha de marketing viral), On-Demand é geralmente a resposta mais segura. Se o cenário enfatiza previsibilidade e otimização de custo com padrão de tráfego conhecido, Provisioned com Auto Scaling é mais indicado.
4. Consistência de leitura
- Eventually consistent read (padrão): pode retornar dados que não refletem a escrita mais recente (a propagação entre réplicas internas do DynamoDB pode levar um curto instante) — mas é mais barata (metade do custo em RCU) e tem menor latência.
- Strongly consistent read (opcional, via parâmetro explícito na requisição): garante que a leitura reflete todas as escritas confirmadas até aquele momento — custa o dobro em RCU e não está disponível em leituras feitas a partir de Global Secondary Indexes (GSIs), apenas na tabela base ou em Local Secondary Indexes (LSIs).
💡 Para a prova: "ler o valor imediatamente após escrevê-lo, com garantia de que reflete a escrita mais recente" → strongly consistent read. Lembre-se: essa opção não existe para leituras via GSI — se o cenário exige consistência forte justamente numa consulta que passa por um GSI, isso é uma contradição que a questão pode estar testando.
5. Índices secundários: GSI vs LSI
| Recurso | Global Secondary Index (GSI) | Local Secondary Index (LSI) |
|---|---|---|
| Partition key do índice | Pode ser diferente da tabela base | Sempre a mesma da tabela base |
| Sort key do índice | Independente | Diferente da sort key da tabela base, mas ainda dentro da mesma partition key |
| Quando pode ser criado | A qualquer momento (inclusive depois da tabela já existir) | Somente na criação da tabela — não pode ser adicionado depois |
| Capacidade | Tem sua própria capacidade provisionada (RCU/WCU), consumida separadamente | Compartilha a capacidade da tabela base |
| Consistência de leitura | Apenas eventually consistent | Suporta strongly consistent |
| Limite por tabela | Até 20 (padrão, ajustável) | Até 5 |
💡 Para a prova: a pegadinha mais comum é "criar um LSI numa tabela que já existe" — isso não é possível; LSIs só podem ser definidos no momento da criação da tabela. Se o cenário precisa de um novo padrão de consulta numa tabela já em produção, a resposta é GSI, não LSI.
Um GSI, por consumir capacidade própria, também introduz um ponto de atenção: escritas na tabela base geram escritas correspondentes no GSI (para manter os índices atualizados) — se o GSI estiver subprovisionado, ele pode causar throttling mesmo que a tabela base tenha capacidade de sobra.
6. Single-table design
Um padrão avançado (e bastante cobrado na prova de forma conceitual) em que múltiplos tipos de entidade (usuários, pedidos, produtos) são armazenados na mesma tabela física, usando prefixos na partition key e sort key para diferenciá-los (ex: PK = USER#123 vs PK = PRODUCT#456).
Exemplo de itens numa única tabela:
PK = USER#123 SK = PROFILE → dados do usuário
PK = USER#123 SK = ORDER#20260808#1 → um pedido do usuário
PK = PRODUCT#456 SK = METADATA → dados do produto
Vantagens: menos operações de consulta (uma única query pode retornar múltiplos tipos de entidade relacionados, já que compartilham partition key), menor latência agregada, custo potencialmente menor por reduzir o número de requisições.
Desvantagens: modelagem significativamente mais complexa que num banco relacional tradicional, exige planejar todos os padrões de acesso antes de desenhar as chaves (ao contrário do modelo relacional, onde novas consultas podem ser criadas depois via JOIN), e geralmente exige atributos de tipo (ex: um atributo entityType) para diferenciar itens ao processar resultados.
💡 Para a prova: single-table design é uma otimização válida quando os padrões de acesso são conhecidos com antecedência e a prioridade é minimizar número de requisições/latência — não é uma prática obrigatória, e multi-table continua sendo uma opção válida (e mais simples) quando a modelagem relacional entre entidades é pouco previsível.
7. DynamoDB Accelerator (DAX)
DAX é um cache in-memory, totalmente gerenciado, especificamente compatível com a API do DynamoDB — reduz latência de leituras de milissegundos de dois dígitos para microssegundos, para cargas de trabalho de leitura intensa.
- Funciona como um cache transparente: a aplicação aponta para o endpoint do DAX em vez do endpoint direto da tabela, e o DAX repassa para o DynamoDB nos cache misses.
- Reduz a carga (e o custo de RCU) na tabela base para leituras repetidas do mesmo item.
- Não substitui strongly consistent reads em todos os casos: DAX é otimizado para leituras eventualmente consistentes; para strongly consistent reads, as requisições passam direto para o DynamoDB, sem passar pelo cache.
💡 Para a prova: "aplicação de leitura intensiva que precisa de latência em microssegundos" → DAX. Não confundir com ElastiCache, que é um cache genérico (Redis/Memcached) para qualquer tipo de dado, não especificamente integrado à API do DynamoDB.
8. DynamoDB Streams, TTL e transações
- DynamoDB Streams: captura, em ordem, um log de alterações (inserções, atualizações, remoções) feitas na tabela — consumido tipicamente por uma função Lambda via event source mapping, permitindo reagir a mudanças em tempo quase real (ex: sincronizar dados com outro sistema, disparar notificações, manter agregações atualizadas).
- TTL (Time to Live): permite marcar itens para expiração automática, definindo um atributo com um timestamp Unix — o DynamoDB remove o item automaticamente após essa data, sem consumir capacidade de escrita adicional para a remoção, útil para dados temporários (sessões, cache, logs com retenção limitada).
- Transações (DynamoDB Transactions): permitem agrupar múltiplas operações de leitura ou escrita, em uma ou mais tabelas, garantindo atomicidade (tudo ou nada) — útil quando uma operação de negócio precisa atualizar múltiplos itens de forma consistente (ex: debitar de uma conta e creditar em outra simultaneamente).
9. Segurança
- IAM policies: controlam acesso em nível de API (quem pode fazer
GetItem,PutItem,Queryetc.), inclusive com granularidade em nível de item/atributo através de condições baseadas em chave (ex: um usuário só pode acessar itens onde a partition key corresponde ao seu próprio ID). - Criptografia em repouso: habilitada por padrão em todas as tabelas, via chave gerenciada pela AWS ou uma chave KMS própria (customer managed key), sem necessidade do processo de "snapshot + cópia" que RDS/EBS exigem para mudar de chave — a configuração de criptografia pode ser ajustada diretamente.
- VPC Endpoints: permitem que instâncias numa VPC acessem o DynamoDB sem que o tráfego saia pela internet pública, mesmo o DynamoDB sendo um serviço "público" por padrão (não vive dentro de uma VPC como o RDS).
10. DynamoDB vs RDS — quando escolher cada um
| Critério | DynamoDB | RDS |
|---|---|---|
| Modelo de dados | Chave-valor/documento, schema flexível por item | Relacional, schema fixo, com JOINs |
| Escala de escrita | Horizontal, praticamente ilimitada | Vertical (uma instância); Aurora oferece mais flexibilidade |
| Latência | Milissegundos consistentes, em qualquer escala | Variável, geralmente maior sob carga alta |
| Consultas complexas (JOIN, agregações ad-hoc) | Fraco — exige modelagem antecipada dos padrões de acesso | Forte — SQL permite consultas flexíveis não previstas de antemão |
| Transações multi-item | Suportado, mas mais limitado que SQL tradicional | Suportado nativamente e de forma madura (ACID completo) |
| Caso de uso típico | Alto volume, baixa latência, padrões de acesso conhecidos (carrinhos, sessões, catálogos, IoT) | Sistemas com relações complexas entre entidades, relatórios ad-hoc, necessidade de SQL |
💡 Para a prova: se o cenário menciona "consultas ad-hoc complexas com múltiplos JOINs" ou "relatórios flexíveis não previstos com antecedência", pense RDS. Se menciona "escala massiva", "latência de milissegundos em qualquer volume", ou "padrão de acesso conhecido e previsível" (ex: carrinho de compras, sessões de usuário, dados de IoT), pense DynamoDB.
11. Boas práticas
- Escolha a partition key com alta cardinalidade e distribuição uniforme de acesso, evitando hot partitions.
- Use On-Demand para cargas de trabalho novas ou imprevisíveis; migre para Provisioned + Auto Scaling quando o padrão de tráfego for bem conhecido e otimização de custo importar mais.
- Prefira eventually consistent reads por padrão (mais barato), reservando strongly consistent reads apenas para os casos que realmente exigem a garantia.
- Crie GSIs para novos padrões de consulta em tabelas já existentes; planeje LSIs apenas na criação da tabela, se necessário.
- Use DAX para cargas de leitura intensiva sensíveis a latência de microssegundos.
- Configure TTL para dados com validade natural, evitando crescimento indefinido da tabela e custo de armazenamento desnecessário.
- Planeje os padrões de acesso antes de desenhar as chaves — ao contrário do modelo relacional, corrigir a modelagem depois é significativamente mais custoso no DynamoDB.
12. Como cai na certificação
- Cenário "alto volume de tráfego concentrado numa única chave causando throttling" → hot partition; redesenhar a chave (maior cardinalidade ou write sharding).
- Cenário "ler o dado imediatamente após escrever, com garantia da versão mais recente" → strongly consistent read (lembrando que não está disponível via GSI).
- Cenário "novo padrão de consulta necessário numa tabela já em produção" → GSI (LSI só pode ser criado junto com a tabela).
- Cenário "tráfego novo, sem histórico, ou picos difíceis de prever" → modo de capacidade On-Demand.
- Cenário "tráfego previsível, otimização de custo relevante" → Provisioned com Auto Scaling.
- Cenário "leitura intensiva precisando de latência em microssegundos" → DAX.
- Cenário "reagir em tempo quase real a mudanças na tabela" → DynamoDB Streams, tipicamente com Lambda.
- Cenário "expirar dados automaticamente sem custo de escrita adicional" → TTL.
- Cenário "atualizar múltiplos itens de forma atômica" → DynamoDB Transactions.
- Cenário "consultas ad-hoc complexas com múltiplos JOINs ou relatórios flexíveis" → RDS, não DynamoDB.
13. Exercícios práticos
- Projete as chaves (PK/SK) para armazenar usuários e seus pedidos numa única tabela, permitindo consultas por usuário e por período de datas.
- Explique como você detectaria e mitigaria uma hot partition em produção, incluindo pelo menos uma métrica do CloudWatch que ajudaria no diagnóstico.
- Compare eventually consistent e strongly consistent reads, e explique um cenário de negócio onde usar eventual consistency por engano causaria um bug real.
- Um time precisa adicionar um novo padrão de consulta numa tabela já em produção há meses. Explique por que a opção "criar um LSI" não está disponível nesse cenário, e qual é a alternativa correta.
- Descreva um cenário de negócio onde DynamoDB seria uma escolha melhor que RDS, e outro onde RDS seria mais adequado — justificando com base nos padrões de acesso.
14. Questões de Revisão
Questão 1
Uma API grava eventos de sensores IoT usando `deviceId` como partition key. Um dispositivo específico envia milhares de eventos por minuto, e a aplicação começa a sofrer throttling mesmo com capacidade agregada aparentemente suficiente na tabela. Qual é a causa mais provável?
Questão 2
Uma aplicação precisa ler o estado mais recente de um item imediatamente após uma escrita bem-sucedida, com garantia de que a leitura reflete exatamente essa escrita. Qual tipo de leitura deve ser usado?
Questão 3
Ao modelar pedidos de um e-commerce, é necessário consultar todos os pedidos de um usuário, ordenados por data, numa única operação eficiente. Qual desenho de chave é mais adequado?
Questão 4
Uma equipe precisa adicionar um novo índice a uma tabela DynamoDB que já está em produção há meses, para suportar um novo padrão de consulta que usa uma partition key diferente da tabela base. Qual opção é viável?
Questão 5
Uma aplicação de leitura intensiva precisa reduzir a latência de consultas repetidas de milissegundos de dois dígitos para a faixa de microssegundos, sem alterar a lógica de acesso da aplicação de forma significativa. Qual recurso resolve isso?
Questão 6
Uma aplicação precisa remover automaticamente registros de sessão de usuário após 24 horas, sem consumir capacidade de escrita adicional para essa remoção. Qual recurso do DynamoDB atende esse requisito?
Questão 7
Uma aplicação de e-commerce precisa gerar relatórios ad-hoc complexos, com múltiplos JOINs entre pedidos, clientes e produtos, que mudam de forma imprevisível conforme a necessidade do time de análise. Qual serviço é mais adequado para esse requisito específico?
Laboratório Prático
Objetivo: criar uma tabela DynamoDB com partition key e sort key, inserir itens simulando um padrão single-table, adicionar um GSI, e observar throttling causado por uma hot partition simulada.
Pré-requisitos: conta AWS com permissão para DynamoDB e IAM.
Tempo estimado: 30 minutos
Possíveis custos: praticamente nulo dentro do free tier para poucas operações de teste.
Passos:
- Crie uma tabela DynamoDB com
PK(partition key, string) eSK(sort key, string), em modo de capacidade Provisioned, com valores baixos de RCU/WCU (ex: 1 cada) para facilitar observar throttling. - Insira alguns itens simulando usuários e pedidos (ex:
PK = USER#1,SK = PROFILE;PK = USER#1,SK = ORDER#2026-08-01#001). - Crie um Global Secondary Index com uma partition key diferente (ex: indexado por um atributo
email), e confirme que ele pode ser adicionado sem recriar a tabela. - Execute uma consulta (
Query) filtrando porPK = USER#1e observe que todos os itens daquele usuário são retornados numa única operação, ordenados pela sort key. - Simule uma hot partition: escreva repetidamente múltiplos itens usando o mesmo valor de partition key em rápida sucessão (ex: um script simples fazendo várias chamadas
PutItemseguidas com a mesmaPK), até observar erros de throttling (ProvisionedThroughputExceededException) no console ou nos logs, dado o baixo WCU provisionado. - Corrija aumentando o WCU provisionado (ou mudando para On-Demand) e repita o teste, observando que o throttling desaparece.
Resultado esperado: você confirma na prática como a partition key concentra tráfego numa única partição física, como isso gera throttling mesmo em uma tabela pequena, e como GSIs podem ser adicionados a qualquer momento sem recriar a tabela.
Limpeza dos recursos: delete a tabela DynamoDB criada no laboratório (isso remove automaticamente os GSIs associados a ela).
Referências:
- Amazon DynamoDB Developer Guide: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html
- Partições e distribuição de dados: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html
- Modos de capacidade (Provisioned e On-Demand): https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html
- Consistência de leitura: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html
- GSI vs LSI: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html
- Amazon DynamoDB Accelerator (DAX): https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.html
- DynamoDB Streams: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html