Limites et quotas DynamoDB, vérifiés contre le service en direct
Quelles sont les limites DynamoDB ?
Un item est plafonné à 400 KB, une clé de partition à 2 048 octets et une clé de tri à 1 024 octets. Une écriture par lot prend 25 items, une lecture par lot 100 clés, une transaction 100 actions. Une table a droit à 20 index secondaires globaux et 5 locaux. Chacun de ces chiffres sur cette page a été établi en envoyant la requête à Amazon DynamoDB et en lisant ce qui revenait.
Comment ces chiffres ont été établis
AWS publie ses quotas sans preuve, et c'est normalement très bien — jusqu'à ce qu'un chiffre porte une décision de conception et que tu veuilles savoir s'il signifie 400 000 octets ou 409 600, s'il compte tes noms d'attributs, et ce que le service dit exactement quand tu le dépasses.
Alors on les a sondées. Pour chaque limite du premier tableau ci-dessous, une
requête a été construite pour tomber exactement sur la valeur documentée
et envoyée au service en direct dans us-east-1 ; puis une seconde requête,
une unité au-delà. La première doit être acceptée et la seconde rejetée —
c'est cette paire qui localise le bord, plutôt que de croire la documentation
sur parole. Le message de rejet dans la dernière colonne est la phrase du
service elle-même, capturée verbatim et jamais retapée.
Quatre lignes n'ont pu être établies que du côté du rejet. Ce sont des
limites CreateTable dont le côté acceptation signifierait construire une
table avec vingt index et attendre que chacun devienne actif, pour un chiffre
que le rejet énonce directement. La colonne Comment ça a été établi
indique laquelle est laquelle ; ce n'est pas de la décoration.
Limites vérifiées
| Limite | Valeur | Comment ça a été établi | Ce que le service renvoie quand tu la dépasses |
|---|---|---|---|
| Taille maximale d'un item | 409 600 octets | Accepté à 409 600, rejeté à 409 601 | ValidationException: Item size has exceeded the maximum allowed size |
| Valeur maximale de clé de partition | 2 048 octets | Accepté à 2 048, rejeté à 2 049 | ValidationException: One or more parameter values were invalid: Size of hashkey has exceeded the maximum size limit of2048 bytes |
| Valeur maximale de clé de tri | 1 024 octets | Accepté à 1 024, rejeté à 1 025 | ValidationException: One or more parameter values were invalid: Aggregated size of all range keys has exceeded the size limit of 1024 bytes |
| Profondeur d'imbrication maximale | 32 niveaux | Accepté à 32, rejeté à 33 | ValidationException: 1 validation error detected: Nesting Levels have exceeded supported limits: Attributes in the item have nested levels beyond supported limit |
| Longueur maximale d'expression | 4 096 octets | Accepté à 4 096, rejeté à 4 097 | ValidationException: 1 validation error detected: Invalid ConditionExpression: Expression size has exceeded the maximum allowed size; |
| Items maximum par BatchWriteItem | 25 items | Accepté à 25, rejeté à 26 | ValidationException: 1 validation error detected: Value '<your request>' at 'requestItems' failed to satisfy constraint: Map value must satisfy constraint: [Member must have length less than or equal to 25, Member must have length greater than or equal to 1] |
| Clés maximum par BatchGetItem | 100 items | Accepté à 100, rejeté à 101 | ValidationException: 1 validation error detected: Value at 'RequestItems.<table-name>.member.Keys' failed to satisfy constraint: Member must have length less than or equal to 100 |
| Actions maximum par TransactWriteItems | 100 items | Accepté à 100, rejeté à 101 | ValidationException: 1 validation error detected: Value '<your request>' at 'transactItems' failed to satisfy constraint: Member must have length less than or equal to 100 |
| Index secondaires globaux par table | 20 | Rejet uniquement | ValidationException: One or more parameter values were invalid: GlobalSecondaryIndex count exceeds the per-table limit of 20 |
| Index secondaires locaux par table | 5 | Rejet uniquement | ValidationException: One or more parameter values were invalid: Number of LocalSecondaryIndexes exceeds per-table limit of 5 |
| Attributs non-clé projetés par index | 20 | Rejet uniquement | ValidationException: 1 validation error detected: Value '<your request>' at 'globalSecondaryIndexes.1.member.projection.nonKeyAttributes' failed to satisfy constraint: Member must have length less than or equal to 20 |
| Attributs non-clé projetés par table | 100 | Rejet uniquement | ValidationException: One or more parameter values were invalid: Number of projected attributes in all indexes exceeds limit of 100, number of projected attributes:120 |
Environnement : Amazon DynamoDB, service en direct, us-east-1, sondé le
2026-08-27 avec le AWS SDK for JavaScript v3.
Ce que les sondes ont révélé
400 KB signifie 409 600 octets, et ça compte tes noms d'attributs. Un item mesuré à exactement 409 600 octets a été accepté ; 409 601 a été rejeté. La mesure compte la longueur UTF-8 de chaque nom d'attribut plus chaque valeur, ce qui est le même calcul que celui qu'implémente notre calculateur de taille d'item — la sonde construit sa charge utile avec cette bibliothèque, donc les deux s'accordent par construction plutôt que par affirmation. Le problème de modélisation plus profond derrière cette limite a son propre guide : la limite de taille d'item DynamoDB.
La limite d'attributs projetés que tout le monde cite est la mauvaise. La
page Quotas
d'AWS documente un seul chiffre — « up to 100 attributes combined for all of a
table's local and global secondary indexes » — et ne mentionne jamais de
plafond par index. Il y en a un, et c'est 20. Un CreateTable qui
projette 21 attributs non-clé dans un seul index est rejeté bien avant que le
total par table n'approche 100. Le 20 est documenté, mais seulement dans la
page
Projection
de l'API Reference, comme une contrainte de membre de tableau : « Maximum
number of 20 items ». Si tu conçois un index en te fiant uniquement à la page
Quotas, l'API refusera un schéma que la page Quotas dit correct. Les deux
chiffres sont dans le tableau ci-dessus, chacun avec le rejet qui le prouve.
Deux des messages contiennent les propres coquilles d'AWS, reproduites ici
plutôt que corrigées en silence — maximum size limit of2048 bytes manque un
espace, et number of projected attributes:120 en manque un autre. Si tu
grep tes logs pour ces chaînes, grep ce que le service envoie, pas ce qui se
lit correctement.
Les clés de tri sont mesurées en agrégat. Le rejet de clé de tri dit « Aggregated size of all range keys », pas « the sort key », parce que le même budget de 1 024 octets couvre la clé de tri de la table et celle de chaque index secondaire local où l'item atterrit.
La page de 1 MB, qui ne lève rien du tout
Chaque limite ci-dessus s'annonce en te rejetant. La limite de page de Query
et Scan, non. Dépasse-la et DynamoDB renvoie une page courte et un
LastEvaluatedKey, sans erreur et sans avertissement — c'est pourquoi « mon
Scan n'a renvoyé qu'une partie de la table » est une surprise si courante, et
pourquoi la pagination n'est pas facultative.
Ça veut aussi dire qu'il n'y a aucun message d'erreur à citer, donc ça a été mesuré plutôt que provoqué :
À 1 000 octets par item, une page a tenu 1 029 items et a renvoyé un LastEvaluatedKey — 1 029 000 octets de données d'item, avec le 1 030e item laissé pour la requête suivante. À 5 000 octets par item, une page a tenu 208 items et a renvoyé un LastEvaluatedKey — 1 040 000 octets de données d'item, avec le 209e item laissé pour la requête suivante.
Aucune des deux pages ne tenait 1 MiB de données d'item — la première manquait d'environ 19 576 octets. Donc le budget de page facture plus par item que les octets propres de l'item.
Deux sondes à des tailles d'item différentes suffisent à cerner ça. En traitant une page comme items × (item bytes + per-item overhead) ≤ budget, seuls 7 surcoûts en octets entiers sont cohérents avec les deux mesures, et exactement un d'entre eux place le budget sur un mégaoctet binaire rond : un surcoût de 19 octets par item, avec un budget entre 1 048 551 et 1 048 971 octets — une plage contenant 1 048 576. Le « 1 MB » de DynamoDB est binaire, comme le dit sa propre page de quotas, et il est dépensé en octets d'item plus le surcoût par item. Prévois environ 19 octets de ça par item.
Quotas que nous n'avons pas sondés
Les limites ci-dessous sont citées d'après AWS, pas mesurées. Ce sont des quotas au niveau du compte : la plupart sont ajustables sur demande, et les atteindre signifie provisionner un débit qui facture à l'heure, créer des milliers de tables, ou s'engager sur un an de capacité réservée. Rien de tout ça n'est une sonde, donc rien n'est présenté comme telle. La source de chaque ligne est la page AWS Quotas in Amazon DynamoDB.
| Quota | Valeur par défaut | Ajustable | Pourquoi nous ne l'avons pas sondé |
|---|---|---|---|
| Tables par compte et par Région | 2 500 | Oui | Créer 2 500 tables pour observer la 2 501e échouer laisse un compte que quelqu'un doit ensuite démonter. |
| Débit provisionné par table | 40 000 RCU et 40 000 WCU | Oui | Provisionner 40 000 unités facture à l'heure, qu'une seule requête soit faite ou non. |
| Débit provisionné par compte | 80 000 RCU et 80 000 WCU | Oui | La même raison, deux fois — et ça change un réglage à l'échelle du compte. |
| Débit on-demand par table | 40 000 RRU et 40 000 WRU | Oui | L'atteindre signifie soutenir 40 000 requêtes par seconde, ce qui est un test de charge avec une facture. |
| Capacité réservée active par compte | 1 000 000 unités de capacité | Oui | La capacité réservée est un engagement d'achat d'un an, pas une sonde. |
| Taille de table | Aucune limite pratique | — | AWS affirme que les tables ne sont pas contraintes en items ni en octets ; il n'y a pas de bord à trouver. |
Sur quelles limites concevoir
La plupart, tu ne les rencontreras jamais. La poignée qui façonne les conceptions réelles :
- 400 KB par item est une contrainte de modélisation, pas un quota. Un item qui s'en approche est généralement une relation one-to-many non bornée stockée comme une liste embarquée. Voir la limite de taille d'item.
- La page de 1 MB gouverne chaque Query et Scan que tu écris. Le code qui
ignore
LastEvaluatedKeydevient silencieusement faux le jour où tes données dépassent une page. - 25 items par écriture par lot et 100 par lecture par lot façonnent tes boucles de chargement en masse. Voir les opérations par lots.
- 100 actions par transaction est celle que les gens rencontrent en essayant de faire se comporter DynamoDB de façon relationnelle. Voir les transactions.
- 20 GSIs, 5 LSIs, 100 attributs projetés contraignent la conception des patterns d'accès bien plus souvent que les quotas de débit, et le nombre de LSI est figé au moment où la table est créée. Voir les projections d'index et GSI vs LSI.
La plupart des rejets cités ci-dessus ont aussi leur propre page sous
Erreurs DynamoDB, avec la requête qui produit chacun
d'eux. Les quatre rejets CreateTable n'en ont pas — ils ont été capturés
pour cette page.
Pour vérifier un seul item contre la barre des 400 KB sans l'écrire, le calculateur de taille d'item tourne dans ton navigateur. Pour regarder les items de tes propres tables, DynoTable est un client DynamoDB de bureau.