Comprenez ce qu’est Amazon DynamoDB, comment fonctionne son modèle NoSQL, et découvrez des patterns pratiques pour concevoir des systèmes scalables à faible latence et des microservices.

Amazon DynamoDB est un service de base de données NoSQL entièrement géré par AWS, conçu pour des applications nécessitant des lectures et écritures à faible latence de façon constante, à pratiquement n’importe quelle échelle. « Entièrement géré » signifie qu’AWS prend en charge le travail d’infrastructure — approvisionnement matériel, réplication, patching et beaucoup de tâches opérationnelles — afin que les équipes puissent se concentrer sur la livraison de fonctionnalités plutôt que sur l’exploitation des serveurs de base de données.
Au cœur, DynamoDB stocke des données sous forme d’items (lignes) dans des tables, mais chaque item peut avoir des attributs flexibles. Le modèle de données se comprend mieux comme un mélange de :
Les équipes choisissent DynamoDB quand elles veulent des performances prévisibles et des opérations simplifiées pour des charges de travail qui ne se prêtent pas bien aux jointures relationnelles. Il est couramment utilisé pour les microservices (chaque service possédant ses données), les applications serverless à trafic en rafales, et les systèmes pilotés par événements qui réagissent aux changements de données.
Ce billet passe en revue les briques de base (tables, clés et index), comment modéliser selon les patterns d’accès (y compris la conception table-unique), comment fonctionnent la montée en charge et les modes de capacité, et des patterns pratiques pour streamer les changements dans une architecture événementielle.
DynamoDB s’organise autour de quelques blocs simples, mais les détails comptent car ils déterminent comment vous modélisez les données et à quelle vitesse (et à quel coût) les requêtes seront servies.
Une table est le conteneur de haut niveau. Chaque enregistrement dans une table est un item (similaire à une ligne), et chaque item est un ensemble d’attributs (similaire à des colonnes).
Contrairement aux bases relationnelles, les items dans une même table n’ont pas besoin de partager les mêmes attributs. Un item peut avoir {status, total, customerId}, tandis qu’un autre inclut {status, shipmentTracking} — DynamoDB n’exige pas de schéma fixe.
Chaque item est identifié de façon unique par une clé primaire, et DynamoDB supporte deux types :
En pratique, les clés composites permettent des accès groupés comme « toutes les commandes d’un client, les plus récentes en premier ».
Un Query lit des items par clé primaire (ou par la clé d’un index). Il cible une partition key spécifique et peut filtrer par plages de sort key — c’est la voie efficace et recommandée.
Un Scan parcourt toute la table (ou l’index) puis filtre. C’est facile à démarrer, mais généralement plus lent et plus coûteux à grande échelle.
Quelques contraintes à connaître :
Ces fondamentaux conditionnent les patterns d’accès, les choix d’indexation et les caractéristiques de performance.
DynamoDB est souvent décrit à la fois comme un magasin clé-valeur et comme une base de documents. C’est exact, mais il est utile de comprendre ce que chacun implique dans la conception quotidienne.
Au fond, vous récupérez les données par clé. Fournissez les valeurs de la clé primaire et DynamoDB retourne un item. Cette recherche par clé est ce qui fournit un stockage à latence prévisible pour de nombreuses charges.
En même temps, un item peut contenir des attributs imbriqués (maps et listes), ce qui le fait ressembler à une base de documents : vous pouvez stocker des payloads structurés sans définir un schéma rigide à l’avance.
Les items se prêtent naturellement à des données JSON-like :
profile.name, profile.address).C’est adapté quand une entité est généralement lue en entier — profil utilisateur, panier d’achat ou bundle de configuration.
DynamoDB ne supporte pas les jointures côté serveur. Si votre appli doit récupérer « une commande plus ses lignes plus le statut d’expédition » en un seul parcours, vous dé-normaliserez souvent : copier des attributs dans plusieurs items, ou intégrer de petites sous-structures directement dans un item.
La dé-normalisation augmente la complexité à l’écriture et peut créer un fan-out de mises à jour. Le gain est moins d’aller-retour et des lectures plus rapides — souvent critique pour des systèmes scalables.
Les requêtes DynamoDB les plus rapides s’expriment comme « donne-moi cette partition » (et éventuellement « dans cette partition, donne-moi cette plage »). Le choix des clés concerne donc surtout comment vous lisez les données, pas seulement comment vous les stockez.
La partition key détermine quelle partition physique stocke un item. DynamoDB hashe cette valeur pour répartir données et trafic. Si de nombreuses requêtes convergent vers un petit ensemble de valeurs de partition key, vous pouvez créer des partitions « chaudes » et atteindre des limites de débit même si la table est globalement peu utilisée.
Bonnes partition keys :
"GLOBAL")Avec une sort key, les items partageant la même partition key sont stockés ensemble et ordonnés par la sort key. Cela permet efficacement :
BETWEEN, begins_with)Un pattern courant est de composer la sort key, par exemple TYPE#id ou TS#2025-12-22T10:00:00Z, pour supporter plusieurs formes de requêtes sans multiplier les tables.
PK = USER#<id> (simple GetItem)PK = USER#<id>, SK begins_with ORDER# (ou SK = CREATED_AT#...)PK = DEVICE#<id>, SK = TS#<timestamp> avec BETWEEN pour des fenêtres temporellesSi votre partition key s’aligne sur vos requêtes les plus volumineuses et distribue uniformément, vous obtenez des lectures/écritures à faible latence de façon constante. Sinon, vous compensez par des scans, des filtres ou des indexes supplémentaires — chacun ajoutant du coût et augmentant le risque de clés chaudes.
Les index secondaires offrent des chemins de requête alternatifs au-delà de la clé primaire de la table. Plutôt que de remodeler votre table de base chaque fois qu’un nouveau pattern d’accès apparaît, vous pouvez ajouter un index qui re-clés les mêmes items pour une autre requête.
Un Global Secondary Index (GSI) possède sa propre partition key (et une sort key optionnelle) qui peut être complètement différente de celle de la table. Il est « global » car il traverse toutes les partitions de la table et peut être ajouté ou supprimé à tout moment. Utilisez un GSI quand vous avez besoin d’un nouveau pattern d’accès qui ne rentre pas dans la clé originale — par exemple, interroger des commandes par customerId alors que la table est indexée par orderId.
Un Local Secondary Index (LSI) partage la même partition key que la table de base mais utilise une sort key différente. Les LSI doivent être définis à la création de la table. Ils sont utiles pour avoir plusieurs ordres de tri au sein du même groupe d’entités (même partition key), comme récupérer les commandes d’un client triées par createdAt vs status.
La projection détermine quels attributs DynamoDB stocke dans l’index :
Chaque écriture sur la table de base peut déclencher des écritures dans un ou plusieurs indexes. Plus de GSI et des projections larges augmentent le coût d’écriture et la consommation de capacité. Planifiez les indexes autour des patterns d’accès stables et minimisez les attributs projetés quand c’est possible.
La montée en charge DynamoDB commence par un choix : On-Demand ou Provisioned. Les deux peuvent atteindre un très haut débit, mais se comportent différemment face aux variations de trafic.
On-Demand est la solution la plus simple : vous payez par requête et DynamoDB s’ajuste automatiquement à la charge variable. C’est adapté aux trafics imprévisibles, aux produits en phase early-stage et aux charges en rafales où vous ne voulez pas gérer des cibles de capacité.
Provisioned consiste à planifier la capacité : vous spécifiez un débit de lecture et d’écriture (ou vous l’auto-scalez) et obtenez des coûts plus prévisibles pour une utilisation stable. C’est souvent moins cher pour des charges connues et pour les équipes capables de prévoir la demande.
Le débit provisionné se mesure en :
La taille de l’item et le pattern d’accès déterminent le coût réel : items plus grands, consistance forte et scans peuvent consommer rapidement la capacité.
L’auto-scaling ajuste les RCUs/WCUs provisionnés selon des cibles d’utilisation. Il aide pour la croissance graduelle et les cycles prévisibles, mais n’est pas instantané. Les pics soudains peuvent toujours provoquer du throttling si la capacité ne monte pas assez vite, et il ne corrige pas une partition chaude qui concentre le trafic.
DynamoDB Accelerator (DAX) est un cache en mémoire qui peut réduire la latence de lecture et décharger les lectures répétées (ex. pages produit populaires, sessions). Il est utile quand de nombreux clients demandent souvent les mêmes items ; il n’aide pas les patterns à forte écriture et ne remplace pas une bonne conception de clés.
DynamoDB vous permet d’arbitrer entre garanties de lecture, latence et coût, il est donc important d’être explicite sur ce que signifie « correct » pour chaque opération.
Par défaut, GetItem et Query utilisent des lectures éventuellement consistantes : vous pouvez brièvement voir une valeur antérieure juste après une écriture. C’est souvent acceptable pour des flux, catalogues produits et autres vues majoritairement en lecture.
Avec des lectures fortement consistantes (option possible pour des lectures depuis la table de base dans une région), DynamoDB garantit que vous voyez la dernière écriture reconnue. La consistance forte coûte plus en capacité de lecture et peut augmenter la latence en queue, donc réservez-la aux lectures vraiment critiques.
La consistance forte est utile pour des lectures qui conditionnent des actions irréversibles :
Pour des compteurs, l’approche la plus sûre est généralement une mise à jour atomique (ex. UpdateItem avec ADD) plutôt que « lire fort puis écrire », pour éviter les pertes d’incréments.
Les transactions DynamoDB (TransactWriteItems, TransactGetItems) fournissent des sémantiques ACID sur jusqu’à 25 items. Elles sont utiles lorsque vous devez mettre à jour plusieurs items ensemble — par exemple écrire une commande et réserver l’inventaire — ou faire respecter des invariants qui ne tolèrent pas d’états intermédiaires.
Les retries sont normales dans les systèmes distribués. Rendre les écritures idempotentes pour que les réessais n’induisent pas d’effets en double :
ConditionExpression (ex. “créer seulement si attribute_not_exists”)L’exactitude avec DynamoDB consiste surtout à choisir le bon niveau de consistance et à concevoir les opérations pour que les réessais ne corrompent pas les données.
DynamoDB répartit les données d’une table sur plusieurs partitions physiques. Chaque partition a un débit limité pour les lectures/écritures, ainsi qu’une capacité de stockage. Votre partition key détermine où vit un item ; si trop de requêtes ciblent la même valeur de partition key (ou un petit ensemble), cette partition devient le goulot d’étranglement.
Les partitions chaudes proviennent souvent de choix de clés qui concentrent le trafic : une clé « globale » comme USER#1, TENANT#default, ou STATUS#OPEN, ou des patterns ordonnés dans le temps où tout le monde écrit sur « maintenant » sous une même partition.
Vous verrez typiquement :
ProvisionedThroughputExceededException) pour un sous-ensemble de clésConcevez pour la distribution d’abord, puis pour la commodité des requêtes :
TENANT#<id> au lieu d’une constante partagée).ORDER#<id>#<shard> pour répartir les écritures sur N shards, puis interroger across shards si nécessaire.METRIC#2025-12-22T10) pour éviter que « toutes les écritures aillent dans l’item le plus récent ».Pour des pics imprévisibles, la capacité on-demand peut absorber les rafales (dans les limites du service). En mode provisioned, utilisez l’auto-scaling et implémentez un backoff exponentiel avec jitter côté client sur les throttles pour éviter des réessais synchronisés qui amplifient le pic.
La modélisation DynamoDB part des patterns d’accès, pas des diagrammes ER. Vous concevez les clés pour que les requêtes nécessaires deviennent des Query rapides, tandis que le reste est évité ou traité de façon asynchrone.
La « conception table-unique » consiste à stocker plusieurs types d’entités (utilisateurs, commandes, messages) dans une seule table et à utiliser des conventions de clés cohérentes pour récupérer des données liées en un seul Query. Cela réduit les allers-retours inter-entités et maintient une latence prévisible.
Une approche commune est les clés composites :
PK groupe une partition logique (ex. USER#123)SK ordonne les items dans ce groupe (ex. PROFILE, ORDER#2025-12-01, MSG#000123)Cela permet de récupérer « tout pour un utilisateur » ou « seulement les commandes d’un utilisateur » en choisissant un préfixe de sort-key.
Pour des relations en graphe, une adjacency list fonctionne bien : stocker les arêtes comme items.
PK = USER#123, SK = FOLLOWS#USER#456Pour supporter les recherches inverses ou un véritable many-to-many, ajoutez un item d’arête inversée ou projetez sur un GSI selon les chemins de lecture.
Pour les événements et métriques, évitez des partitions non bornées en bucketant :
PK = DEVICE#9#2025-12-22 (device + jour)SK = TS#1734825600 (timestamp)Utilisez TTL pour expirer automatiquement les anciens points, et conservez des agrégats (rollups horaires/journaliers) comme items séparés pour des tableaux de bord rapides.
Si vous voulez un rappel plus approfondi sur les conventions de clé, voir /blog/partition-key-and-sort-key-design.
DynamoDB Streams est le mécanisme natif de capture des changements (CDC). Lorsqu’il est activé sur une table, chaque insert, update ou delete produit un enregistrement de stream que des consommateurs en aval peuvent traiter — sans interroger la table.
Un enregistrement de stream contient les clés et (optionnellement) l’ancienne et/ou la nouvelle image de l’item, selon le stream view type choisi (keys only, new image, old image, both). Les enregistrements sont regroupés en shards, que vous lisez séquentiellement.
Un montage courant est DynamoDB Streams → AWS Lambda, où chaque lot d’enregistrements déclenche une fonction. D’autres consommateurs sont possibles (consommateurs personnalisés, ou envoi vers systèmes d’analytics/logging).
Workflows typiques :
Cela permet de garder la table primaire optimisée pour des lectures/écritures à faible latence tout en déléguant le travail dérivé aux consommateurs asynchrones.
Streams fournit un traitement ordonné par shard (qui corrèle typiquement avec la partition key), mais pas un ordre global sur toutes les clés. La livraison est au moins une fois, donc des doublons peuvent survenir.
Pour gérer cela de manière sûre :
Conçus avec ces garanties en tête, les Streams transforment DynamoDB en une base solide pour des systèmes pilotés par événements.
DynamoDB est conçu pour une haute disponibilité en répartissant les données sur plusieurs Zones de Disponibilité dans une région. Pour la plupart des équipes, les gains pratiques en fiabilité viennent d’une stratégie claire de sauvegarde, de la compréhension des options de réplication et de la surveillance des métriques pertinentes.
Les backups on-demand sont des snapshots manuels (ou automatisés) que vous prenez lorsque vous voulez un point de restauration connu — avant une migration, après une release, ou avant un backfill important. Ils sont pratiques pour des « signets ».
Le Point-in-Time Recovery (PITR) capture continuellement les changements pour restaurer la table à n’importe quelle seconde dans la fenêtre de rétention. PITR est le filet de sécurité contre des suppressions accidentelles, de mauvais déploiements ou des écritures malformées qui passent les validations.
Si vous avez besoin de résilience multi-région ou de lectures à faible latence proches des utilisateurs, les Global Tables répliquent les données entre régions sélectionnées. Elles simplifient la planification de bascule, mais introduisent des délais de réplication cross-region et des considérations de résolution de conflits — clarifiez donc les patterns d’écriture et la propriété des items.
Au minimum, alertez sur :
Ces signaux font souvent remonter des problèmes de partition chaude, une capacité insuffisante ou des patterns d’accès inattendus.
Pour du throttling, identifiez d’abord le pattern d’accès en cause, puis atténuez en passant temporairement à on-demand ou en augmentant la capacité provisionnée, et envisagez de sharder les clés chaudes.
Pour des pannes partielles ou des erreurs élevées, réduisez le rayon d’impact : désactivez le trafic non critique, réessayez avec backoff et jitter, et dégradez gracieusement (par ex. servir des lectures en cache) jusqu’à stabilisation de la table.
La sécurité DynamoDB concerne surtout qui peut appeler quelles actions API, depuis où et sur quelles clés. Puisque les tables peuvent contenir plusieurs types d’entités (et parfois plusieurs tenants), le contrôle d’accès doit être conçu en parallèle du modèle de données.
Commencez par des politiques IAM basées sur l’identité qui limitent les actions (ex. dynamodb:GetItem, Query, PutItem) au strict nécessaire et scopez-les aux ARNs de tables spécifiques.
Pour un contrôle plus fin, utilisez dynamodb:LeadingKeys pour restreindre l’accès selon les valeurs de partition key — utile quand un service ou tenant ne doit lire/écrire que dans son propre keyspace.
DynamoDB chiffre les données au repos par défaut en utilisant des clés AWS-owned ou une KMS gérée par le client. Si vous avez des exigences de conformité, vérifiez :
Pour le chiffrement en transit, assurez-vous que les clients utilisent HTTPS (les SDK AWS le font par défaut). Si vous terminez TLS dans un proxy, confirmez que le saut entre le proxy et DynamoDB reste chiffré.
Utilisez un VPC Gateway Endpoint pour DynamoDB afin que le trafic reste sur le réseau AWS et que vous puissiez appliquer des politiques d’endpoint pour contraindre l’accès. Associez cela à des contrôles d’egress (NACLs, security groups et routage) pour éviter des chemins « tout peut atteindre l’internet public ».
Pour des tables partagées, incluez un identifiant tenant dans la partition key (par ex. TENANT#<id>), puis faites respecter l’isolation avec des conditions IAM sur dynamodb:LeadingKeys.
Si vous avez besoin d’une isolation plus forte, envisagez des tables séparées par tenant ou par environnement, et réservez les designs de table partagée aux cas où la simplicité opérationnelle et l’efficacité des coûts l’emportent sur un rayon d’impact réduit.
DynamoDB est souvent « bon marché quand vous êtes précis, coûteux quand vous êtes vague ». Les coûts suivent surtout vos patterns d’accès, donc le meilleur travail d’optimisation commence par expliciter ces patterns.
Votre facture est principalement impactée par :
Une surprise courante : chaque écriture sur la table est aussi une écriture sur chaque GSI affecté, donc « encore un index » peut multiplier le coût d’écriture.
Une bonne conception de clés réduit le besoin d’opérations coûteuses. Si vous vous retrouvez souvent à utiliser Scan, vous payez pour lire des données que vous jetez.
Préférez :
Query par partition key (et éventuellement conditions sur la sort key)Si un pattern d’accès est rare, envisagez de le servir via une table séparée, un job ETL, ou un read-model mis en cache plutôt que d’ajouter un GSI permanent.
Utilisez TTL pour supprimer automatiquement les items à vie courte (sessions, tokens temporaires, états intermédiaires). Cela réduit le stockage et peut garder les indexes plus petits dans le temps.
Pour des données append-only (événements, logs), combinez TTL avec des designs de sort-key qui permettent d’interroger « récent seulement », afin de ne pas toucher l’historique froid régulièrement.
En mode provisioned, fixez des baselines conservatrices et scalez avec l’auto-scaling basé sur des métriques réelles. En on-demand, surveillez les patterns inefficaces (items volumineux, clients bavards) qui font monter le volume de requêtes.
Considérez Scan comme dernier recours — quand vous devez réellement traiter toute la table, planifiez-le hors-pointe ou exécutez-le comme batch contrôlé avec pagination et backoff.
DynamoDB excelle quand votre application peut s’exprimer comme un ensemble de patterns d’accès bien définis et que vous avez besoin d’une latence faible et constante à grande échelle. Si vous pouvez décrire vos lectures et écritures à l’avance (par partition key, sort key et quelques indexes), c’est souvent l’un des moyens les plus simples d’exploiter un store hautement disponible.
DynamoDB est un bon choix lorsque vous avez :
Cherchez ailleurs si vos besoins principaux incluent :
Beaucoup d’équipes gardent DynamoDB pour les lectures/écritures « chaudes » et ajoutent :
Si vous validez des patterns d’accès et des conventions table-unique, la rapidité compte. Les équipes prototypent parfois le service et l’interface dans Koder.ai (plateforme vibe-coding qui construit web, backend et mobile depuis une conversation) puis itèrent sur la conception des clés DynamoDB à mesure que des chemins de requête réels émergent. Même si le backend final diffère, des prototypes bout-en-bout aident à révéler quelles requêtes doivent être des Query plutôt que des scans coûteux.
Validez : (1) vos principales requêtes sont connues et basées sur des clés, (2) les besoins de consistance correspondent au modèle choisi, (3) la taille attendue des items et leur croissance sont comprises, et (4) le modèle de coût (on-demand vs provisioned + autoscaling) convient à votre budget.
DynamoDB est une base de données NoSQL entièrement gérée par AWS, conçue pour des lectures/écritures à faible latence de manière constante à très grande échelle. Les équipes l’utilisent lorsqu’elles peuvent définir des schémas d’accès basés sur des clés (récupérer par ID, lister par propriétaire, requêtes par intervalle de temps) et veulent éviter d’administrer l’infrastructure de base de données.
C’est particulièrement fréquent dans les architectures microservices, les applications serverless et les systèmes pilotés par événements.
Une table contient des items (semblables à des lignes). Chaque item est un ensemble flexible d’attributs (semblables à des colonnes) et peut inclure des données imbriquées.
DynamoDB est adapté lorsque qu’une requête a généralement besoin « de l’entité complète », car les items peuvent contenir des maps et des lists (structures de type JSON).
Une partition key seule identifie de façon unique un item (clé primaire simple). Une partition key + sort key (clé composite) permet à plusieurs items de partager la même partition key tout en restant identifiables de façon unique et ordonnés par la sort key.
Les clés composites permettent des patterns comme :
Utilisez Query quand vous pouvez spécifier la partition key (et éventuellement une condition sur la sort key). C’est la voie rapide et scalable.
N’utilisez Scan que lorsque vous devez vraiment lire tout le contenu ; il parcourt l’ensemble de la table ou de l’index puis filtre, ce qui est généralement plus lent et coûteux.
Si vous scannez fréquemment, c’est un signe que votre conception de clé ou d’index doit être revue.
Les index secondaires offrent des chemins de requête alternatifs.
Les index augmentent le coût d’écriture car les écritures sont répliquées dans l’index.
Choisissez On-Demand si le trafic est imprévisible, en pics, ou si vous ne voulez pas gérer la capacité. Vous payez à la requête.
Choisissez Provisioned si l’utilisation est stable/prévisible et que vous souhaitez un coût plus contrôlé. Associez-le à l’auto-scaling, en gardant en tête qu’il ne réagit pas instantanément aux pics soudains.
Par défaut, les lectures sont éventuellement consistantes, ce qui signifie que vous pouvez brièvement lire une valeur plus ancienne juste après une écriture.
Utilisez des lectures fortement consistantes pour les contrôles cruciaux qui doivent être à jour, comme des validations d’autorisation ou l’état d’un workflow.
Pour la correction en concurrence, préférez les mises à jour atomiques (par ex. écritures conditionnelles ou ADD) plutôt que des boucles lire-modifier-écrire.
Les transactions (TransactWriteItems, TransactGetItems) fournissent des garanties ACID sur jusqu’à 25 items.
Utilisez-les lorsque vous devez mettre à jour plusieurs items ensemble (par ex. créer une commande et réserver du stock) ou faire respecter des invariants qui ne tolèrent pas d’états partiels.
Elles coûtent plus et ajoutent de la latence, réservez-les aux flux qui en ont vraiment besoin.
Les partitions « chaudes » se produisent quand trop de requêtes ciblent la même valeur de partition key (ou un petit ensemble de valeurs), entraînant du throttling même si la table est globalement sous-utilisée.
Mitigations courantes :
Activez DynamoDB Streams pour obtenir un flux de changements sur insertions, mises à jour et suppressions. Un pattern courant est Streams → Lambda pour déclencher du travail en aval.
Garanties importantes :
Faites en sorte que les consommateurs soient (upsert par clé, écritures conditionnelles, ou suivi des IDs d’événements traités).