Intermédiaire9 min de lecture

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

LimiteValeurComment ça a été établiCe que le service renvoie quand tu la dépasses
Taille maximale d'un item409 600 octetsAccepté à 409 600, rejeté à 409 601ValidationException: Item size has exceeded the maximum allowed size
Valeur maximale de clé de partition2 048 octetsAccepté à 2 048, rejeté à 2 049ValidationException: One or more parameter values were invalid: Size of hashkey has exceeded the maximum size limit of2048 bytes
Valeur maximale de clé de tri1 024 octetsAccepté à 1 024, rejeté à 1 025ValidationException: One or more parameter values were invalid: Aggregated size of all range keys has exceeded the size limit of 1024 bytes
Profondeur d'imbrication maximale32 niveauxAccepté à 32, rejeté à 33ValidationException: 1 validation error detected: Nesting Levels have exceeded supported limits: Attributes in the item have nested levels beyond supported limit
Longueur maximale d'expression4 096 octetsAccepté à 4 096, rejeté à 4 097ValidationException: 1 validation error detected: Invalid ConditionExpression: Expression size has exceeded the maximum allowed size;
Items maximum par BatchWriteItem25 itemsAccepté à 25, rejeté à 26ValidationException: 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 BatchGetItem100 itemsAccepté à 100, rejeté à 101ValidationException: 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 TransactWriteItems100 itemsAccepté à 100, rejeté à 101ValidationException: 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 table20Rejet uniquementValidationException: One or more parameter values were invalid: GlobalSecondaryIndex count exceeds the per-table limit of 20
Index secondaires locaux par table5Rejet uniquementValidationException: One or more parameter values were invalid: Number of LocalSecondaryIndexes exceeds per-table limit of 5
Attributs non-clé projetés par index20Rejet uniquementValidationException: 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 table100Rejet uniquementValidationException: 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.

QuotaValeur par défautAjustablePourquoi nous ne l'avons pas sondé
Tables par compte et par Région2 500OuiCréer 2 500 tables pour observer la 2 501e échouer laisse un compte que quelqu'un doit ensuite démonter.
Débit provisionné par table40 000 RCU et 40 000 WCUOuiProvisionner 40 000 unités facture à l'heure, qu'une seule requête soit faite ou non.
Débit provisionné par compte80 000 RCU et 80 000 WCUOuiLa même raison, deux fois — et ça change un réglage à l'échelle du compte.
Débit on-demand par table40 000 RRU et 40 000 WRUOuiL'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 compte1 000 000 unités de capacitéOuiLa capacité réservée est un engagement d'achat d'un an, pas une sonde.
Taille de tableAucune limite pratiqueAWS 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 LastEvaluatedKey devient 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.

Mis à jour