Migrações no DynamoDB Sem Downtime
Vindo do SQL, uma migração é um ALTER TABLE que trava a tabela enquanto reescreve toda
linha. O DynamoDB não tem schema para alterar — itens são schemaless, então adicionar um
atributo ou um novo tipo de entidade é grátis.
A parte difícil é o padrão de acesso que os novos dados têm que servir, e remodelar dados vivos para servi-lo sem uma reescrita que para o mundo.
Como migrar uma tabela do DynamoDB sem downtime?
O DynamoDB não tem ALTER TABLE, então migrações nunca travam a tabela. Você adiciona atributos, uma nova forma de chave ou um novo online com UpdateTable, depois remodela os dados progressivamente: faça backfill dos itens antigos preguiçosamente na leitura ou com uma varredura controlada, e use dual-write em ambos os formatos durante a transição. Não existe um corte de dia D.
- Não existe
ALTER TABLE. Itens são schemaless. Uma "migração" significa adicionar atributos, uma nova forma de chave ou um novo índice — nunca reescrever um conjunto fixo de colunas. - Escritas novas são fáceis; itens antigos são o problema. As linhas existentes não carregam os novos atributos, então qualquer índice ou consulta nova silenciosamente os perde até você fazer o backfill.
- Adicione índices online, faça backfill preguiçosamente.
UpdateTableconstrói um GSI em uma tabela ativa; faça backfill de itens antigos na leitura (preguiçoso) ou com uma varredura controlada — nunca um corte de dia D. - Faça dual-write durante a transição. Enquanto ambas as formas coexistem, escreva o formato antigo e o novo juntos para que nenhum caminho de leitura fique defasado.
Enquadre como um padrão de acesso, não uma coluna
Digamos que você administre um produto SaaS de workspace em uma tabela. Itens usam
PK = "WS#<id>" e SK sobrecarregada por entidade:
| PK | SK | attributes |
|---|---|---|
| WS#a91 | META | name, tier |
| WS#a91 | DOC#2026-04-01#x7 | title, author, body |
| WS#a91 | DOC#2026-04-02#k2 | title, author, body |
Agora o produto quer comentários em documentos, mais uma nova leitura: "liste todo comentário que um membro escreveu no workspace, mais novos primeiro." Essa última cláusula é a migração. Um novo tipo de entidade sozinho é trivial; servir uma consulta que as chaves atuais não conseguem responder é o trabalho.
Adicione o novo tipo de entidade primeiro
Comentários são apenas novos itens na mesma partição — sem cerimônia de migração, sem tabela nova:
| PK | SK | attributes |
|---|---|---|
| WS#a91 | DOC#2026-04-01#x7#CMT#01HZ... | author, text, createdAt |
Um Query em PK = "WS#a91" com SK begins_with "DOC#2026-04-01#x7#CMT#" já lista os
comentários de um documento. Documentos existentes ficam intocados. Essa metade lança no
dia um — veja coleções de itens e chaves sobrecarregadas
para por que a mesma partição contém ambos.
A nova consulta precisa de um GSI
"Todos os comentários de um membro, mais novos primeiro" não pode ser servido pela
tabela base — memberId não é nem a PK nem um prefixo de SK. Isso é um novo índice,
e escolhê-lo corretamente é uma decisão própria: veja GSI vs LSI
(um LSI precisa existir na criação da tabela, então para uma migração em uma tabela
ativa um GSI é sua única opção).
Adicione um GSI1 genérico e escreva os novos atributos em itens de comentário
novos:
| GSI1PK | GSI1SK |
|---|---|
| MEMBER#u44 | 2026-04-02T09:15:00Z |
Query GSI1 WHERE GSI1PK = "MEMBER#u44" com ScanIndexForward = false dá comentários
mais novos primeiro por membro.
Construa o índice online
UpdateTable adiciona um GSI a uma tabela ativa sem downtime. O DynamoDB faz backfill
dos itens existentes no índice em segundo plano; o índice reporta
CREATING/backfilling até terminar, depois vira ACTIVE
(Gerenciando GSIs).
Duas ciladas aqui. Primeiro, a AWS avisa que adicionar um GSI pode causar throttling
nas escritas da tabela base se a nova chave distribuir de forma desigual — adicione-o
em uma janela de baixo tráfego e observe o CloudWatch. Segundo, o índice é
eventualmente consistente mesmo depois de ficar ACTIVE; uma escrita pode não estar
visível no GSI por um momento. Veja
por que GSIs são eventualmente consistentes.
Faça backfill dos itens antigos
O GSI só indexa itens que têm GSI1PK/GSI1SK. Seus comentários pré-migração —
escritos antes de o atributo existir — nunca aparecem, mesmo depois de o backfill
completar. O backfill de GSI online copia itens existentes, mas não pode inventar
atributos que não estão neles. Você precisa adicionar os valores.
Duas estratégias:
| Estratégia | Como funciona | Use quando |
|---|---|---|
| Preguiçosa | Na leitura de um item antigo, escreva de volta os novos atributos | Itens antigos são lidos com frequência; dilua o custo |
| Varredura | Um Scan paginado atualiza todo item antigo uma vez | Você precisa do GSI completo até um prazo |
Para a varredura, pagine com Scan, e para cada comentário antigo adicione os atributos
de índice com um UpdateItem condicional para que você nunca atropele uma escrita
concorrente.
A condição protege contra o atributo já existir. Monte e copie a ConditionExpression e
a UpdateExpression exatas com o
DynamoDB Expression Builder em vez de digitar à
mão attribute_not_exists(GSI1PK).
Faça dual-write durante a transição
Até todo item antigo carregar os novos atributos, duas formas coexistem. O caminho de escrita precisa popular o novo formato em toda escrita — comentários novos e qualquer atualização de um antigo — para que a lacuna só encolha.
Escolha uma condição de término de backfill que você possa verificar: a varredura paginou a tabela inteira, ou o caminho preguiçoso rodou tempo suficiente para que itens não convertidos estejam defasados por design. Só então você remove o caminho de leitura antigo. Pular isso é como uma migração "completa" enquanto uma fração das consultas silenciosamente retorna resultados curtos.

Ciladas
- Adicionar o atributo ≠ feito o backfill. Um novo GSI começa vazio para itens antigos. Verifique a cobertura antes de confiar na consulta.
- Mudar uma chave no lugar não é uma migração — é uma reescrita. Você não pode mutar
a
PK/SKde um item; você escreve um novo item sob a nova chave e exclui o antigo. Planeje como copiar-depois-excluir, com dual-read no meio. - Sem corte transacional. Não há momento em que a tabela inteira vira. Projete todo passo para ser seguro enquanto ambas as formas estão vivas.
Próximos passos
Verifique as novas chaves e coleções sobrecarregadas em single-table design, e confirme que o backfill está completo paginando a tabela ativa. Experimente o DynoTable para navegar na sua tabela, identificar itens sem backfill e rodar as atualizações condicionais contra seus próprios dados.


