Les transactions DynamoDB
Une transaction DynamoDB regroupe plusieurs écritures en une seule opération tout-ou-rien : soit chaque action est validée, soit aucune ne l'est. C'est ainsi que tu empêches deux items liés de se désynchroniser quand une écriture échoue à moitié.
Dans le scénario du journal d'audit, chaque événement que tu ajoutes devrait aussi
incrémenter un eventCount par tenant. Si l'événement atterrit mais pas le compteur —
ou l'inverse — le journal et le compte se contredisent pour toujours. Une transaction
rend ça impossible.
DynamoDB prend-il en charge les transactions ?
Oui. DynamoDB prend en charge les transactions ACID via TransactWriteItems et
TransactGetItems, qui regroupent jusqu'à 100 actions en une seule opération
tout-ou-rien sur une ou plusieurs tables. Soit chaque écriture est validée, soit
aucune ne l'est, ce qui empêche les items liés de se désynchroniser. Les écritures
transactionnelles coûtent deux fois la capacité des écritures normales, et une condition
échouée ou un conflit annule l'ensemble de la requête.
TransactWriteItemsregroupe jusqu'à 100 actions d'écriture sur une ou plusieurs tables, en tout-ou-rien. La taille agrégée des items ne peut pas dépasser 4 Mo.- Les actions sont
Put,Update,DeleteetConditionCheck. UnConditionCheckaffirme quelque chose sur un item que tu n'écris pas. - Ça coûte le double. Une écriture transactionnelle consomme deux fois la capacité d'une écriture normale — DynamoDB prépare puis valide.
- Les conflits et les conditions échouées annulent l'ensemble avec une
TransactionCanceledException; rien de partiel n'est laissé derrière.
Le problème : deux écritures qui doivent s'accorder
Tu veux que chaque nouvel événement d'audit incrémente aussi le compteur courant du tenant. Fait en deux appels distincts, toute défaillance entre les deux corrompt tes données :
PutItemdu nouvel itemEVENT#…— réussit.UpdateItempourADD eventCount 1— expire en timeout.
Maintenant le journal a une ligne de plus que ce que prétend le compteur. Réessayer l'étape 2 à l'aveugle risque de double-compter ; ne pas réessayer les laisse incohérents. Il n'y a pas de récupération sûre car les deux écritures n'ont jamais été liées.
Venant de SQL, tu envelopperais les deux dans BEGIN … COMMIT. La réponse de DynamoDB
est une unique requête transactionnelle qui porte les deux écritures ensemble.
Comment fonctionne TransactWriteItems
D'après le
guide du développeur AWS,
TransactWriteItems « regroupe jusqu'à 100 actions d'écriture en une seule opération
tout-ou-rien » ciblant jusqu'à 100 items distincts, et « la taille agrégée des items de
la transaction ne peut pas dépasser 4 Mo ». Les actions s'achèvent de façon atomique —
toutes réussissent ou aucune.
Tu peux mélanger quatre types d'action dans une transaction :
Put— créer ou remplacer un item.Update— modifier des attributs (y comprisADDpour notre compteur).Delete— supprimer un item par clé.ConditionCheck— affirmer une condition sur un item que tu n'écris pas par ailleurs (par ex. « ce tenant est toujours actif »).
Deux règles supplémentaires mordent en pratique. D'abord, les transactions consomment le double de la capacité des écritures non transactionnelles équivalentes — DynamoDB fait une phase de préparation et une phase de validation. Ensuite, tu ne peux pas cibler le même item deux fois dans une transaction, et les transactions ne peuvent pas être exécutées contre des index.
Un exemple concret : ajouter + compter, de façon atomique
Retour au journal d'audit. Ajouter un événement pour le tenant acme et incrémenter
son compteur, c'est une transaction à deux actions :
| action | item | effet | |
|---|---|---|---|
| Put | TENANT#acme | EVENT#2026-06-24T09:14Z#a1 | écrire la nouvelle ligne d'audit |
| Update | TENANT#acme | COUNTER | ADD eventCount 1 |
Si la condition de l'une des actions échoue — disons un ConditionCheck que le tenant
n'est pas suspendu — la requête entière est annulée avec une
TransactionCanceledException et aucune des deux écritures n'a lieu. Le journal et
le compteur ne peuvent jamais se contredire.
Le ConditionExpression de chaque action est le levier. Pour affirmer que la ligne de
l'événement n'existe pas déjà (afin qu'un réessai ne puisse pas la dupliquer) et que le
tenant est actif, tu composes des conditions comme attribute_not_exists(SK) sur le
Put et status = :active comme ConditionCheck.
Construis et copie ces expressions de condition typées dans le
DynamoDB Expression Builder plutôt que d'assembler
à la main les ExpressionAttributeNames et les placeholders :val — le mode écriture
conditionnelle émet exactement la forme que veut TransactWriteItems.
Pour des réessais sûrs sur une connexion instable, attache un client token : un
TransactWriteItems répété avec le même token dans les 10 minutes renvoie un succès
sans réappliquer les écritures
(idempotence).
Fais-le dans DynoTable
DynoTable utilise les transactions en interne pour ses propres écritures : quand tu mets
en attente plusieurs modifications d'items et que tu les valides, il les envoie sous
forme de TransactWriteItems avec des expressions de condition de verrouillage
optimiste, donc ton lot de modifications est tout-ou-rien — tu n'appliques jamais à
moitié un changement multi-items.
Cela signifie que tu peux modifier la ligne de l'événement et le compteur dans le même lot mis en attente, revoir le diff, et valider les deux de façon atomique sans écrire de code SDK.

Pièges et étapes suivantes
- Prévois le double de capacité. Une écriture transactionnelle facture deux fois la WCU d'une écriture simple — acceptable pour la paire occasionnelle critique pour la cohérence, coûteux si tu enveloppes chaque écriture dans une transaction. Utilise-la là où l'atomicité compte vraiment.
- Gère
TransactionCanceledExceptionexplicitement. Elle est renvoyée pour une condition échouée ou un conflit avec une autre transaction en cours sur les mêmes items. Les raisons d'annulation te disent quelle action a échoué — inspecte-les, ne réessaie pas à l'aveugle. - Les enregistrements de stream ne sont pas conscients des transactions. Les changements d'une transaction se propagent à Streams progressivement et peuvent s'entrelacer avec d'autres ; les consommateurs ne peuvent pas supposer d'atomicité ni d'ordre — voir DynamoDB Streams.
- Pas pour des compteurs à fort débit. Un unique compteur chaud sous une lourde charge transactionnelle concurrente va ralentir ; pour ça, regarde les compteurs atomiques ou le sharding du compteur.
Les transactions sont l'outil pour « ces écritures doivent s'accorder ». Une fois que les événements atterrissent de façon cohérente, la préoccupation suivante est d'y réagir — c'est DynamoDB Streams.
Télécharge DynoTable pour mettre en attente des modifications multi-items et les valider en une seule transaction contre ta propre table.


