Trier DynamoDB sur un attribut changeant
Tu modélises une clé de tri autour d'un attribut pour pouvoir interroger les items dans son ordre — puis l'attribut change. Le statut d'un ticket, l'état d'une commande, la priorité d'une tâche. Voici le piège que te tend DynamoDB : tu ne peux pas mettre à jour un attribut de clé sur place. Une clé primaire est immuable pour toute la vie de l'item. Change une valeur qui fait partie de la clé et tu n'es pas en train d'éditer un item — tu le déplaces, ce que DynamoDB t'oblige à faire explicitement.
Peux-tu modifier une clé de tri DynamoDB ?
Non. Une clé de tri fait partie de la clé primaire, et les attributs de clé DynamoDB sont immuables — UpdateItem ne peut pas modifier la valeur d'une clé de partition ou de tri, et il n'existe pas d'opération « déplacer l'item ». Pour la changer, supprime l'ancien item et fais un put d'un nouveau, ou garde plutôt la valeur volatile sur une clé de tri de GSI.
- Les attributs de clé sont immuables. Tu ne peux pas faire d'
UpdateItemsur une valeur de clé de partition ou de tri — DynamoDB n'a pas d'opération « déplacer l'item ». - Pour changer une valeur de clé, tu supprimes l'ancien item et tu fais un put d'un nouveau — idéalement dans une transaction pour que ce soit atomique.
- Mieux : garde la valeur volatile hors de la clé de la table de base et mets-la sur une clé de tri de GSI — les clés de GSI peuvent changer, car mettre à jour l'item de base ne fait que re-propager l'entrée d'index.
- Choisis des clés de tri qui ne changent pas (horodatages, ids immuables) chaque fois que le mode d'accès le permet.
Le problème : un statut sur lequel tu veux trier, mais qui n'arrête pas de changer
Disons que tu gères un service d'assistance et que tu veux lister les tickets d'une équipe triés par statut, alors tu mets le statut dans la clé de tri :
PK: TEAM#7 SK: STATUS#open#TICKET#8842Maintenant le ticket passe à pending. Tu aimerais simplement faire un UpdateItem de la clé de tri vers
STATUS#pending#TICKET#8842 — mais DynamoDB rejette toute écriture qui change un attribut de
clé. La clé est l'adresse de l'item ; tu ne peux pas éditer l'adresse sur place. Le
statut que tu as choisi pour trier est précisément la chose qui ne tient pas en place.
Option 1 : supprimer et recréer (de façon atomique)
Si la valeur doit vivre dans la clé de la table de base, la changer signifie retirer l'ancien item et écrire le nouveau :
1. DeleteItem PK=TEAM#7 SK=STATUS#open#TICKET#8842
2. PutItem PK=TEAM#7 SK=STATUS#pending#TICKET#8842 (same attributes)Fais-le à l'intérieur d'un TransactWriteItems pour que la suppression et
le put réussissent tous les deux ou échouent tous les deux — sinon un crash entre les deux perd le
ticket ou le duplique. Ça marche, mais chaque changement de statut représente désormais deux écritures plus une
transaction ; correct pour des changements occasionnels, coûteux pour ceux qui sont fréquents.
Option 2 : garder la valeur mutable hors de la clé de base (préférable)
La conception la plus propre : fais de la clé de la table de base quelque chose d'immuable (l'id du ticket) et mets la valeur volatile et triable sur une clé de tri de GSI.
Base: PK: TICKET#8842 status: "open" teamId: TEAM#7
GSI: GSI1PK: TEAM#7 GSI1SK: STATUS#open#TICKET#8842Maintenant, changer le statut est un simple UpdateItem sur l'attribut status de l'item de base —
ce que DynamoDB autorise, car status n'est pas une clé de la table de base. DynamoDB
re-propage alors l'entrée du GSI automatiquement vers sa nouvelle position triée. Un seul appel API,
avec l'atomicité gérée pour toi — pas de transaction, pas de danse de suppression (sous le capot, DynamoDB
supprime quand même l'ancienne entrée d'index et écrit la nouvelle, donc un changement indexé coûte environ 3
unités d'écriture contre environ 4 pour une suppression-et-put transactionnelle).
Le compromis : le GSI est en cohérence à terme et coûte du stockage/des écritures supplémentaires — mais pour une valeur qui change souvent, c'est un peu moins cher (environ 3 contre 4 unités d'écriture) et bien plus simple que supprimer-et-recréer à chaque changement.
Concevoir les clés dans DynoTable
Construis et prévisualise les conditions de clé pour la lecture de base et la lecture du GSI dans le générateur d'expressions DynamoDB.
Dans DynoTable, tu choisis ensuite par quel index une requête passe et tu regardes la valeur volatile se trier sur le GSI pendant que l'item de base conserve sa clé immuable — les deux lectures côte à côte sur des données réelles.

Pièges + étapes suivantes
- N'essaie jamais de faire un
UpdateItemsur un attribut de clé — c'est rejeté ; les valeurs de clé sont fixées pour toute la vie de l'item. - Si tu dois la déplacer, fais delete+put dans une transaction — jamais sous forme de deux écritures non protégées.
- Préfère des clés de base immuables + un GSI pour tout attribut sur lequel tu tries et que tu mutes.
- N'oublie pas la cohérence à terme du GSI — l'entrée re-triée apparaît après un bref délai de propagation.
- Voir aussi : stratégies de clé de tri, GSI vs LSI, transactions.
Tu veux voir comment un attribut mutable se trie sur un GSI par rapport à la table de base ? Télécharge DynoTable et explore tes index directement.
Coût d'écriture : delete-and-put vs mise à jour GSI
Comparaison WCU approximative pour un item ticket de 1 Ko en us-east-1 on-demand (la facturation réelle suit les règles d'arrondi AWS) :
| Motif | Appels API | Impact WCU typique |
|---|---|---|
| Delete + put transactionnel sur la clé de base | TransactWriteItems (2 ops) | ~2× la taille d'item par op en tarification transaction |
Update de l'attribut status ; le GSI se re-propage | Un UpdateItem | Écriture de base + écriture GSI (~2 WCU pour un item 1 Ko + attributs projetés) |
Le chemin GSI évite l'orchestration applicative et élimine la fenêtre où un crash entre delete et put perd la ligne. Tu échanges la cohérence à terme sur la lecture d'index contre des écritures plus simples.
Modélise la taille de ton item et le taux de mise à jour dans le calculateur de tarifs quand les changements de statut partent plusieurs fois par minute.
GSI sparse pour les listes triées par statut
Si seuls les tickets ouverts ont besoin d'une file triée par statut, utilise un
index sparse : écris GSI1PK = TEAM#7 et GSI1SK = STATUS#open#... seulement tant que status = open. Quand le ticket se ferme, retire ou omets les attributs de clé GSI à l'update — l'item sort de l'index sans delete-and-put sur la clé de tri de base.
Ça garde l'index petit et évite d'indexer des tickets fermés que tu ne listes jamais.
Clés de base immuables à préférer
| Champ volatil | SK table de base | Meilleure SK de base | Le champ volatil vit sur |
|---|---|---|---|
| Statut de commande | STATUS#shipped#ORD#99 | ORD#99 | Tri GSI ou attribut |
| Priorité de tâche | P#1#TASK#12 | TASK#12 | Tri GSI |
| Nom d'affichage utilisateur | NAME#alice#USER#5 | USER#5 | Attribut hors clé |
Les timestamps et ids immuables (CREATED#2026-06-27T10:00:00Z, TICKET#8842) font de stables clés de tri de base quand tu as besoin d'ordre chronologique sur la table de base elle-même.
Concevoir le GSI avant de coder
Cartographie les modes d'accès dans l'
outil de single-table design — entre « lister les tickets ouverts par équipe, ordre de priorité » et inspecte les templates GSI1PK / GSI1SK suggérés. Puis construis la condition de clé dans l'
expression builder et émets une requête paginée avec le
query builder pour les tests d'intégration.
Read-your-writes après un changement de statut
Après UpdateItem, une lecture fortement cohérente sur la table de base montre le nouveau status immédiatement. Une requête sur le GSI peut laguer brièvement. Les flux UI qui redirigent vers une file triée par GSI doivent tolérer des lignes périmées ou re-fetcher depuis la table de base par id quand la précision compte.


