Avancé7 min de lecture

Les migrations DynamoDB sans interruption

En venant de SQL, une migration est un ALTER TABLE qui verrouille la table pendant qu'il réécrit chaque ligne. DynamoDB n'a pas de schéma à altérer — les items sont schemaless, donc ajouter un attribut ou un nouveau type d'entité est gratuit.

La partie difficile, c'est le mode d'accès que les nouvelles données doivent servir, et remodeler les données en direct pour le servir sans une réécriture stop-the-world.

Comment migrer une table DynamoDB sans interruption de service ?

DynamoDB n'a pas de ALTER TABLE, donc les migrations ne verrouillent jamais la table. Tu ajoutes des attributs, une nouvelle forme de clé ou un nouveau en ligne avec UpdateTable, puis tu remodèles les données en direct de façon incrémentale : backfille les anciens items paresseusement à la lecture ou avec un balayage limité en débit, et fais du dual-write des deux formats pendant la transition. Il n'y a pas de basculement flag-day.

  • Il n'y a pas de ALTER TABLE. Les items sont schemaless. Une « migration » signifie ajouter des attributs, une nouvelle forme de clé ou un nouvel index — jamais réécrire un ensemble de colonnes fixe.
  • Les nouvelles écritures sont faciles ; les anciens items sont le problème. Les lignes existantes ne portent pas les nouveaux attributs, donc tout nouvel index ou toute nouvelle requête les rate silencieusement jusqu'à ce que tu backfilles.
  • Ajoute les index en ligne, backfille paresseusement. UpdateTable construit un GSI sur une table en direct ; backfille les anciens items à la lecture (paresseux) ou avec un balayage contrôlé — jamais un basculement flag-day.
  • Dual-write pendant la transition. Tant que les deux formes coexistent, écris l'ancien et le nouveau format ensemble pour qu'aucun chemin de lecture ne devienne périmé.

Cadre-le comme un mode d'accès, pas une colonne

Disons que tu gères un produit d'espace de travail SaaS sur une seule table. Les items utilisent PK = "WS#<id>" et un SK surchargé par entité :

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

Maintenant le produit veut des commentaires sur les documents, plus une nouvelle lecture : « lister chaque commentaire qu'un membre a écrit à travers l'espace de travail, le plus récent d'abord. » Cette dernière clause est la migration. Un nouveau type d'entité seul est trivial ; servir une requête que les clés actuelles ne peuvent pas répondre, c'est le travail.

Ajoute d'abord le nouveau type d'entité

Les commentaires ne sont que de nouveaux items dans la même partition — pas de cérémonie de migration, pas de nouvelle table :

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

Un Query sur PK = "WS#a91" avec SK begins_with "DOC#2026-04-01#x7#CMT#" liste déjà les commentaires d'un document. Les documents existants sont intacts. Cette moitié livre le jour un — voir les collections d'items et les clés surchargées pour comprendre pourquoi la même partition contient les deux.

La nouvelle requête a besoin d'un GSI

« Tous les commentaires d'un membre, le plus récent d'abord » ne peut pas être servi par la table de base — memberId n'est ni la PK ni un préfixe de SK. C'est un nouvel index, et le choisir correctement est sa propre décision : voir GSI vs LSI (un LSI doit exister à la création de la table, donc pour une migration sur une table en direct un GSI est ta seule option).

Ajoute un GSI1 générique et écris les nouveaux attributs sur les nouveaux items de commentaire :

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

Query GSI1 WHERE GSI1PK = "MEMBER#u44" avec ScanIndexForward = false donne les commentaires les plus récents d'abord par membre.

Construis l'index en ligne

UpdateTable ajoute un GSI à une table en direct sans interruption. DynamoDB backfille les items existants dans l'index en arrière-plan ; l'index reporte CREATING/backfilling jusqu'à ce que ce soit fait, puis bascule vers ACTIVE (Gérer les GSI).

UpdateTable : ajouter GSI1Statut de l'index : CREATINGBackfill des items existantsStatut : ACTIVEQuery GSI1 sûr

Deux pièges ici. D'abord, AWS prévient qu'ajouter un GSI peut throttler les écritures de la table de base si la nouvelle clé se distribue inégalement — ajoute-le dans une fenêtre à faible trafic et surveille CloudWatch. Ensuite, l'index est à cohérence à terme même après être passé ACTIVE ; une écriture peut ne pas être visible sur le GSI pendant un instant. Voir pourquoi les GSI sont à cohérence à terme.

Backfille les anciens items

Le GSI n'indexe que les items qui ont GSI1PK/GSI1SK. Tes commentaires pré-migration — écrits avant que l'attribut existe — n'apparaissent jamais, même après le backfill. Le backfill de GSI en ligne copie les items existants, mais il ne peut pas inventer des attributs qui ne sont pas dessus. Tu dois ajouter les valeurs.

Deux stratégies :

StratégieComment ça marcheÀ utiliser quand
ParesseuxÀ la lecture d'un ancien item, réécris les nouveaux attributsLes anciens items sont souvent lus ; étale le coût
BalayageUn Scan paginé met à jour chaque ancien item une foisTu as besoin que le GSI soit complet pour une échéance

Pour le balayage, pagine avec Scan, et pour chaque ancien commentaire ajoute les attributs d'index avec un UpdateItem conditionnel pour ne jamais écraser une écriture concurrente.

La condition garde sur l'attribut non déjà existant. Construis et copie la ConditionExpression et l'UpdateExpression exactes avec le DynamoDB Expression Builder plutôt que de taper à la main attribute_not_exists(GSI1PK).

Dual-write pendant la transition

Tant que chaque ancien item ne porte pas les nouveaux attributs, deux formes coexistent. Le chemin d'écriture doit peupler le nouveau format à chaque écriture — nouveaux commentaires et toute mise à jour d'un ancien — pour que l'écart ne fasse que rétrécir.

Choisis une condition de fin de backfill que tu peux vérifier : le balayage a paginé toute la table, ou le chemin paresseux a tourné assez longtemps pour que les items non convertis soient périmés par conception. Seulement alors tu retires l'ancien chemin de lecture. Sauter ça, c'est comment une migration « se termine » pendant qu'une fraction des requêtes renvoie silencieusement des résultats tronqués.

Pagination d'une table dans DynoTable pour repérer les items qui manquent les nouveaux attributs d'index pendant un backfill.
Pagination d'une table dans DynoTable pour repérer les items qui manquent les nouveaux attributs d'index pendant un backfill.

Pièges

  • Ajouter l'attribut ≠ backfillé. Un nouveau GSI démarre vide pour les anciens items. Vérifie la couverture avant de faire confiance à la requête.
  • Changer une clé en place n'est pas une migration — c'est une réécriture. Tu ne peux pas muter la PK/SK d'un item ; tu écris un nouvel item sous la nouvelle clé et tu supprimes l'ancien. Planifie-le comme copier-puis-supprimer, avec dual-read entre les deux.
  • Pas de basculement transactionnel. Il n'y a aucun moment où toute la table bascule. Conçois chaque étape pour être sûre tant que les deux formes sont en direct.

Étapes suivantes

Vérifie la cohérence des nouvelles clés et des collections surchargées dans single-table design, et confirme que le backfill est complet en paginant la table en direct. Essaie DynoTable pour parcourir ta table, repérer les items non backfillés et exécuter les mises à jour conditionnelles sur tes propres données.

Mis à jour