Avanzato7 min di lettura

Migrazioni DynamoDB Senza Downtime

Venendo da SQL, una migrazione è un ALTER TABLE che blocca la tabella mentre riscrive ogni riga. DynamoDB non ha schema da alterare — gli Item sono schemaless, quindi aggiungere un attributo o un nuovo tipo di entità è gratis.

La parte difficile è il pattern di accesso che i nuovi dati devono servire, e rimodellare i dati live per servirlo senza una riscrittura stop-the-world.

Come si esegue una migrazione di una tabella DynamoDB senza downtime?

DynamoDB non ha ALTER TABLE, quindi le migrazioni non bloccano mai la tabella. Aggiungi attributi, una nuova forma di chiave o un nuovo online con UpdateTable, poi rimodella i dati live in modo incrementale: fai il backfill dei vecchi Item in lettura (lazy) o con uno sweep controllato, e usa il dual-write di entrambi i formati durante la transizione. Non esiste un cutover flag-day.

  • Non c'è ALTER TABLE. Gli Item sono schemaless. Una "migrazione" significa aggiungere attributi, una nuova forma di chiave o un nuovo indice — mai riscrivere un insieme fisso di colonne.
  • Le nuove scritture sono facili; i vecchi Item sono il problema. Le righe esistenti non portano i nuovi attributi, quindi ogni nuovo indice o query li manca silenziosamente finché non fai il backfill.
  • Aggiungi indici online, fai il backfill lazy. UpdateTable costruisce un GSI su una tabella live; fai il backfill dei vecchi Item in lettura (lazy) o con uno sweep controllato — mai un cutover flag-day.
  • Dual-write durante la transizione. Mentre entrambe le forme coesistono, scrivi il vecchio e il nuovo formato insieme così nessun percorso di lettura diventa obsoleto.

Inquadralo come pattern di accesso, non come colonna

Diciamo che gestisci un prodotto SaaS workspace su una sola tabella. Gli Item usano PK = "WS#<id>" e SK sovraccaricata per entità:

PKSKattributes
WS#a91METAname, tier
WS#a91DOC#2026-04-01#x7title, author, body
WS#a91DOC#2026-04-02#k2title, author, body

Ora il prodotto vuole i commenti sui documenti, più una nuova lettura: "elenca ogni commento che un membro ha scritto nel workspace, più recenti prima." Quest'ultima clausola è la migrazione. Un nuovo tipo di entità da solo è banale; servire una query a cui le chiavi attuali non possono rispondere è il lavoro.

Aggiungi prima il nuovo tipo di entità

I commenti sono semplicemente nuovi Item nella stessa partizione — nessuna cerimonia di migrazione, nessuna nuova tabella:

PKSKattributes
WS#a91DOC#2026-04-01#x7#CMT#01HZ...author, text, createdAt

Una Query su PK = "WS#a91" con SK begins_with "DOC#2026-04-01#x7#CMT#" elenca già i commenti di un documento. I documenti esistenti restano intatti. Questa metà fa il deploy il giorno uno — vedi item collection e chiavi sovraccaricate per il perché la stessa partizione contiene entrambi.

La nuova query ha bisogno di un GSI

"Tutti i commenti di un membro, più recenti prima" non può essere servito dalla tabella base — memberId non è né la PK né un prefisso SK. È un nuovo indice, e sceglierlo correttamente è una sua decisione: vedi GSI vs LSI (un LSI deve esistere alla creazione della tabella, quindi per una migrazione su una tabella live un GSI è la tua unica opzione).

Aggiungi un GSI1 generico e scrivi i nuovi attributi sui nuovi Item commento:

GSI1PKGSI1SK
MEMBER#u442026-04-02T09:15:00Z

Query GSI1 WHERE GSI1PK = "MEMBER#u44" con ScanIndexForward = false dà commenti più recenti prima per membro.

Costruisci l'indice online

UpdateTable aggiunge un GSI a una tabella live senza downtime. DynamoDB fa il backfill degli Item esistenti nell'indice in background; l'indice riporta CREATING/backfilling finché non è fatto, poi passa a ACTIVE (Managing GSIs).

UpdateTable: aggiungi GSI1Stato indice: CREATINGBackfill degli Item esistentiStato: ACTIVEQuery GSI1 sicura

Due trappole qui. Primo, AWS avverte che aggiungere un GSI può mettere in throttling le scritture della tabella base se la nuova chiave distribuisce in modo non uniforme — aggiungilo in una finestra a basso traffico e osserva CloudWatch. Secondo, l'indice è eventualmente coerente anche dopo che diventa ACTIVE; una scrittura può non essere visibile sul GSI per un momento. Vedi perché i GSI sono eventualmente coerenti.

Fai il backfill dei vecchi Item

Il GSI indicizza solo Item che hanno GSI1PK/GSI1SK. I tuoi commenti pre-migrazione — scritti prima che l'attributo esistesse — non compaiono mai, nemmeno dopo il backfill. Il backfill online del GSI copia gli Item esistenti, ma non può inventare attributi che non sono su di essi. Devi aggiungere i valori.

Due strategie:

StrategiaCome funzionaUsa quando
LazyIn lettura di un vecchio Item, riscrivi i nuovi attributiI vecchi Item sono letti spesso; spalma il costo
SweepUno Scan paginato aggiorna ogni vecchio Item una voltaTi serve il GSI completo entro una scadenza

Per lo sweep, pagina con Scan, e per ogni vecchio commento aggiungi gli attributi dell'indice con un UpdateItem condizionale così non calpesti mai una scrittura concorrente.

La condizione protegge sull'attributo non già esistente. Costruisci e copia la ConditionExpression e l'UpdateExpression esatte con il DynamoDB Expression Builder invece di digitare a mano attribute_not_exists(GSI1PK).

Dual-write durante la transizione

Finché ogni vecchio Item non porta i nuovi attributi, due forme coesistono. Il percorso di scrittura deve popolare il nuovo formato a ogni scrittura — nuovi commenti e ogni update a uno vecchio — così il gap si restringe soltanto.

Scegli una condizione di fine backfill che puoi verificare: lo sweep ha paginato l'intera tabella, oppure il percorso lazy è girato abbastanza a lungo che gli Item non convertiti sono obsoleti per design. Solo allora rimuovi il vecchio percorso di lettura. Saltare questo è come una migrazione "si completa" mentre una frazione di query restituisce silenziosamente risultati corti.

Paginare una tabella in DynoTable per individuare gli Item privi dei nuovi attributi indice durante un backfill.
Paginare una tabella in DynoTable per individuare gli Item privi dei nuovi attributi indice durante un backfill.

Errori

  • Aggiungere l'attributo ≠ backfillato. Un nuovo GSI parte vuoto per i vecchi Item. Verifica la copertura prima di fidarti della query.
  • Cambiare una chiave sul posto non è una migrazione — è una riscrittura. Non puoi mutare la PK/SK di un Item; scrivi un nuovo Item sotto la nuova chiave ed elimini quello vecchio. Pianificalo come copy-then-delete, con dual-read nel mezzo.
  • Nessun cutover transazionale. Non c'è momento in cui l'intera tabella si ribalta. Progetta ogni passo perché sia sicuro mentre entrambe le forme sono live.

Prossimi passi

Verifica le nuove chiavi e le collection sovraccaricate in single-table design, e conferma che il backfill è completo paginando la tabella live. Prova DynoTable per navigare la tua tabella, individuare gli Item non backfillati ed eseguire gli update condizionali sui tuoi dati.

Aggiornato