Quand NE PAS utiliser le single-table design dans DynamoDB
Le single-table design est le conseil par défaut pour DynamoDB, et il le mérite : un
seul Query rend un parent et ses enfants, pas de jointures, pas de N+1.
Mais c'est un compromis — tu achètes de la vitesse de lecture avec un schéma rigide et opaque. Certaines charges ne peuvent pas se permettre ce prix, et leur imposer une seule table est son propre footgun.
Quand ne pas utiliser le single-table design dans DynamoDB ?
Évite le single-table design quand ta charge est de l'analytique OLAP lourde, du CRUD ordinaire sur quelques entités sans rapport entre elles, ou des entités qui scalent et échouent indépendamment. Dans ces cas, plusieurs tables sont plus lisibles, coûtent pareil et restent flexibles. Le single-table design ne l'emporte que quand les modes d'accès sont connus, liés et à fort volume.
- Analytique lourde ? Pas de single-table. Les clés surchargées sont OLAP-hostiles — exporte vers un magasin colonnaire et requête là-bas.
- CRUD ordinaire avec une poignée de modes d'accès ? Une table par entité est très bien, lisible, et ne te coûte rien en performance.
- Des entités qui scalent ou échouent indépendamment ? Des tables séparées te laissent les ajuster, facturer et limiter leur rayon d'impact chacune de leur côté.
- Le single-table l'emporte toujours quand tes modes sont connus, liés et à fort volume — c'est le cas pour lequel il a été conçu.
Sache ce que le single-table coûte vraiment
Le single-table design n'est pas gratuit ; il déplace juste le coût hors du chemin de lecture et sur tout le reste. Tu paies en lisibilité et en flexibilité.
Une table contenant cinq types d'entités derrière PK/SK est difficile à lire,
difficile à prendre en main, et difficile à changer. Un nouveau mode d'accès peut
signifier un backfill à travers chaque type d'item de la partition.
Donc la question n'est pas « le single-table est-il bon ? ». C'est « mes modes d'accès justifient-ils la rigidité ? » Quand non, atteins plusieurs tables.
Ne fais pas de single-table pour une charge analytique
DynamoDB est conçu pour l'OLTP — lectures petites, connues, point-et-plage. L'analytique
est OLAP : GROUP BY, gros agrégats, découpage ad-hoc à travers tout le dataset. Les
deux tirent dans des directions opposées.
Le single-table design rend l'OLAP pire, pas meilleur. Les clés surchargées et les types d'entités mêlés signifient qu'un job analytique doit d'abord démêler quel item est lequel avant de pouvoir sommer quoi que ce soit — l'opposé d'un scan colonnaire propre.
En venant de SQL, le réflexe est d'écrire l'agrégat contre la table en direct. Dans
DynamoDB c'est un Scan complet — tu paies et tu lis chaque item, ce qui est le
footgun du Scan à plein volume.
La solution n'est pas une clé plus maligne. C'est un magasin différent. Le conseil même d'AWS est d'exporter DynamoDB vers S3 et de faire l'analytique avec un moteur de requête comme Athena.
Garde l'OLTP et l'OLAP sur des moteurs séparés (AWS DynamoDB Developer Guide,
S3DataExport.html).
Ne fais pas de single-table pour du CRUD simple
Si ton appli lit et écrit quelques entités sans rapport par leur propre id, et que tu as peut-être trois modes d'accès, le single-table ne t'achète rien.
Prends une table Tenants et une table ApiKeys pour un petit outil B2B :
| TenantId | Name | PlanTier |
|---|---|---|
| TNT-8842 | Northwind | pro |
| KeyId | TenantId | Scope |
|---|---|---|
| KEY-01H9... | TNT-8842 | read-write |
Chaque requête est un GetItem par id, ou un Query sur un GSI clé par TenantId. Il
n'y a pas de fetch parent-et-enfants à optimiser, donc il n'y a rien à gagner pour une
partition surchargée. Deux tables claires se lisent mieux qu'une seule trouble.
Le piège est de cargo-culter le single-table parce que c'est « best practice ». La best practice, c'est access-pattern-first. Si les modes sont triviaux, la forme simple est la bonne forme.
Sépare les tables qui scalent ou échouent indépendamment
Une seule table partage une surface de débit, un backup, un rayon d'impact. Quand deux entités ont des taux d'écriture ou des besoins de durabilité radicalement différents, ce destin partagé devient un handicap.
Imagine un système de suivi de flotte. Les véhicules changent rarement ; leur télémétrie déverse chaque seconde :
| VehicleId | Make | Model | Region |
|---|---|---|---|
| VEH-204 | Volvo | FH16 | eu-west |
| DeviceTs | VehicleId | SpeedKph | Fuel |
|---|---|---|---|
| 2026-06-23T10:00:01Z | VEH-204 | 88 | 0.61 |
Deux tables te laissent provisionner la télémétrie pour un firehose, garder les véhicules minuscules et bon marché, poser un TTL sur la télémétrie seule, et empêcher une tempête d'écritures de télémétrie de throttler les lectures du catalogue de véhicules. Une seule table couple tout ça.
Selon le papier Amazon Dynamo de 2007, le partitionnement et la disponibilité sont des préoccupations de premier ordre — des tables indépendantes te donnent un contrôle indépendant sur les deux.
Cartographie la décision avant de t'engager
Fais passer la charge par une seule porte : les entités sont-elles liées, et les modes sont-ils connus et à fort volume ? Sinon, plusieurs tables.
Voici la décision sous forme de flux — commence en haut et suis la première branche qui correspond :
Seule la feuille en bas à droite mérite le single-table ; tout autre chemin est mieux servi par plus d'une table.
Single vs multiple, face à face
| Facteur | Single-table | Plusieurs tables |
|---|---|---|
| Lectures liées | Un Query, pas de jointures | Jointure côté client ou allers-retours en plus |
| Lisibilité | Clés surchargées opaques | Une entité par table, auto-documentée |
| Nouveau mode d'accès | Souvent un backfill | Ajouter une table ou un GSI en isolation |
| Analytique / OLAP | Hostile — démêler avant d'agréger | Exporter quand même, mais plus propre par entité |
| Scaling indépendant | Débit + rayon d'impact partagés | Ajuster, facturer, TTL et backup séparément |
| Idéal quand | Modes connus, liés, à fort volume | Sans rapport, évolutif ou analytique |
Pièges + étapes suivantes
L'erreur miroir est de sur-corriger — séparer des entités véritablement liées et à fort volume en table-par-entité et reconstruire des jointures à la SQL dans ton appli. C'est le piège N+1 que le single-table tue.
Choisis la forme que les modes d'accès demandent, pas le dogme.
Quand tu modélises des relations, appuie-toi sur le bon type d'index — voir GSI vs LSI avant d'en ajouter un.
Quand tu écris une requête contre un schéma multi-tables, esquisse d'abord le
KeyConditionExpression dans le
DynamoDB Expression Builder.
Comme ça tu attrapes une forme de Scan complet avant qu'elle n'atteigne la production.
Puis essaie DynoTable pour parcourir les deux formes sur tes propres tables et voir laquelle tes modes d'accès veulent vraiment.