Límites y cuotas de DynamoDB, verificados contra el servicio en vivo
¿Cuáles son los límites de DynamoDB?
Un Item está limitado a 400 KB, una clave de partición a 2.048 bytes y una clave de ordenación a 1.024 bytes. Un batch write acepta 25 Items, un batch get 100 claves, una transacción 100 acciones. Una tabla admite 20 índices secundarios globales y 5 locales. Cada una de esas cifras de esta página se estableció enviando la solicitud a Amazon DynamoDB y leyendo lo que respondió.
Cómo se establecieron estas cifras
AWS publica sus cuotas sin evidencia, y normalmente eso está bien — hasta que una cifra pesa en una decisión de diseño y quieres saber si significa 400.000 bytes o 409.600, si cuenta los nombres de tus atributos, y qué dice exactamente el servicio cuando la superas.
Así que las sondeamos. Para cada límite de la primera tabla de abajo, se construyó
una solicitud que se situara exactamente en el valor documentado y se envió al
servicio en vivo en us-east-1; luego una segunda solicitud, una unidad por
encima. La primera debe aceptarse y la segunda rechazarse — ese par es lo que
localiza el borde, en lugar de fiarse de la palabra de la documentación. El
mensaje de rechazo de la última columna es la propia frase del servicio,
capturada textualmente y nunca retecleada.
Cuatro filas solo pudieron establecerse por el lado del rechazo. Son límites de
CreateTable cuyo lado de aceptación significaría crear una tabla con veinte
índices y esperar a que cada uno quede activo, para una cifra que el rechazo
declara directamente. La columna Cómo se estableció dice cuál es cuál; no es
decoración.
Límites verificados
| Límite | Valor | Cómo se estableció | Qué devuelve el servicio al superarlo |
|---|---|---|---|
| Tamaño máximo de Item | 409.600 bytes | Aceptado en 409.600, rechazado en 409.601 | ValidationException: Item size has exceeded the maximum allowed size |
| Valor máximo de clave de partición | 2.048 bytes | Aceptado en 2.048, rechazado en 2.049 | ValidationException: One or more parameter values were invalid: Size of hashkey has exceeded the maximum size limit of2048 bytes |
| Valor máximo de clave de ordenación | 1.024 bytes | Aceptado en 1.024, rechazado en 1.025 | ValidationException: One or more parameter values were invalid: Aggregated size of all range keys has exceeded the size limit of 1024 bytes |
| Profundidad máxima de anidamiento | 32 niveles | Aceptado en 32, rechazado en 33 | ValidationException: 1 validation error detected: Nesting Levels have exceeded supported limits: Attributes in the item have nested levels beyond supported limit |
| Longitud máxima de expresión | 4.096 bytes | Aceptado en 4.096, rechazado en 4.097 | ValidationException: 1 validation error detected: Invalid ConditionExpression: Expression size has exceeded the maximum allowed size; |
| Máximo de Items por BatchWriteItem | 25 Items | Aceptado en 25, rechazado en 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] |
| Máximo de claves por BatchGetItem | 100 Items | Aceptado en 100, rechazado en 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 |
| Máximo de acciones por TransactWriteItems | 100 Items | Aceptado en 100, rechazado en 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 |
| Índices secundarios globales por tabla | 20 | Solo rechazo | ValidationException: One or more parameter values were invalid: GlobalSecondaryIndex count exceeds the per-table limit of 20 |
| Índices secundarios locales por tabla | 5 | Solo rechazo | ValidationException: One or more parameter values were invalid: Number of LocalSecondaryIndexes exceeds per-table limit of 5 |
| Atributos no clave proyectados por índice | 20 | Solo rechazo | 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 |
| Atributos no clave proyectados por tabla | 100 | Solo rechazo | ValidationException: One or more parameter values were invalid: Number of projected attributes in all indexes exceeds limit of 100, number of projected attributes:120 |
Entorno: Amazon DynamoDB, servicio en vivo, us-east-1, sondeado el 2026-08-27
con el AWS SDK para JavaScript v3.
Lo que revelaron las sondas
400 KB significan 409.600 bytes, y cuenta los nombres de tus atributos. Un Item medido exactamente en 409.600 bytes fue aceptado; 409.601 fue rechazado. La medición cuenta la longitud UTF-8 de cada nombre de atributo más cada valor, la misma contabilidad que implementa nuestra calculadora de tamaño de Item — la sonda construye su payload con esa misma librería, así que las dos coinciden por construcción y no por afirmación. El problema de modelado más profundo detrás de este límite tiene su propia guía: el límite de tamaño de Item de DynamoDB.
El límite de atributos proyectados que todo el mundo cita es el equivocado.
La página de cuotas
de AWS documenta una sola cifra — "up to 100 attributes combined for all of a
table's local and global secondary indexes" — y nunca menciona un tope por
índice. Sí existe uno, y es 20. Un CreateTable que proyecta 21 atributos no
clave en un solo índice se rechaza mucho antes de que el total por tabla se
acerque a 100. El 20 está documentado, pero solo en la página de la
Referencia de API para Projection,
como una restricción de miembro de array: "Maximum number of 20 items". Si
planeas un índice basándote solo en la página de cuotas, la API rechazará un
esquema que esa misma página dice que está bien. Ambas cifras están en la tabla
de arriba, cada una con el rechazo que lo demuestra.
Dos de los mensajes contienen erratas propias de AWS, reproducidas aquí en
lugar de corregidas en silencio — a maximum size limit of2048 bytes le falta un
espacio, y a number of projected attributes:120 le falta otro. Si estás
buscando estas cadenas en tus logs con grep, busca lo que envía el servicio, no
lo que se lee correctamente.
Las claves de ordenación se miden en conjunto. El rechazo de clave de ordenación dice "Aggregated size of all range keys" ("tamaño agregado de todas las claves de rango"), no "la clave de ordenación", porque el mismo presupuesto de 1.024 bytes cubre la clave de ordenación de la tabla y la de cada índice secundario local en el que aterriza el Item.
La página de 1 MB, que no dispara nada en absoluto
Todos los límites de arriba se anuncian rechazándote. El límite de página de
Query y Scan no. Lo cruzas y DynamoDB devuelve una página corta y una
LastEvaluatedKey, sin error y sin aviso — por eso "mi Scan solo devolvió parte
de la tabla" es una sorpresa tan común, y por eso
la paginación no es opcional.
Eso también significa que no hay ningún mensaje de error que citar, así que se midió en lugar de provocarse:
Con 1.000 bytes por Item, una página contuvo 1.029 Items y devolvió una
LastEvaluatedKey — 1.029.000 bytes de datos de Item, con el Item 1.030 dejado
para la siguiente solicitud. Con 5.000 bytes por Item, una página contuvo
208 Items y devolvió una LastEvaluatedKey — 1.040.000 bytes de datos de
Item, con el Item 209 dejado para la siguiente solicitud.
Ninguna página llegó a contener 1 MiB de datos de Item — la primera se quedó corta por unos 19.576 bytes. Así que el presupuesto de página cobra más por Item que los propios bytes del Item.
Dos sondas con tamaños de Item distintos bastan para fijar esto. Tratando una
página como Items × (bytes por Item + sobrecarga por Item) ≤ presupuesto, solo
7 sobrecargas en bytes enteros son consistentes con ambas mediciones, y
exactamente una de ellas sitúa el presupuesto en un megabyte binario redondo: una
sobrecarga de 19 bytes por Item, con el presupuesto entre 1.048.551 y
1.048.971 bytes — un rango que contiene 1.048.576. El "1 MB" de DynamoDB es
binario, como indica su propia página de cuotas, y se gasta en bytes de Item más
sobrecarga por Item. Presupuesta unos 19 bytes de eso por Item.
Cuotas que no sondeamos
Los límites de abajo están citados de AWS, no medidos. Son cuotas a nivel de cuenta: la mayoría son ajustables bajo petición, y alcanzarlas significa aprovisionar rendimiento que se factura por hora, crear miles de tablas, o comprometerse a un año de capacidad reservada. Nada de eso es una sonda, así que nada de eso se presenta como tal. La fuente de cada fila es la página de AWS Cuotas en Amazon DynamoDB.
| Cuota | Valor por defecto | Ajustable | Por qué no la sondeamos |
|---|---|---|---|
| Tablas por cuenta y por región | 2.500 | Sí | Crear 2.500 tablas para ver fallar la 2.501 deja una cuenta que alguien tiene que desmontar. |
| Rendimiento aprovisionado por tabla | 40.000 RCU y 40.000 WCU | Sí | Aprovisionar 40.000 unidades se factura por hora, se haga o no una sola solicitud. |
| Rendimiento aprovisionado por cuenta | 80.000 RCU y 80.000 WCU | Sí | El mismo motivo, por partida doble — y cambia un ajuste a nivel de cuenta. |
| Rendimiento bajo demanda por tabla | 40.000 RRU y 40.000 WRU | Sí | Alcanzarlo significa sostener 40.000 solicitudes por segundo, que es una prueba de carga con factura. |
| Capacidad reservada activa por cuenta | 1.000.000 unidades de capacidad | Sí | La capacidad reservada es un compromiso de compra de un año, no una sonda. |
| Tamaño de tabla | Sin límite práctico | — | AWS declara que las tablas no tienen límite de Items ni de bytes; no hay ningún borde que encontrar. |
En qué límites debes basar tu diseño
La mayoría de estos no los alcanzarás nunca. El puñado que sí condiciona diseños reales:
- 400 KB por Item es una restricción de modelado, no una cuota. Un Item que se acerca a ella suele ser una relación uno-a-muchos sin límite guardada como una lista embebida. Consulta el límite de tamaño de Item.
- La página de 1 MB gobierna cada Query y cada Scan que escribas. El código
que ignora
LastEvaluatedKeyestá silenciosamente equivocado el día en que tus datos superen una sola página. - 25 Items por batch write y 100 por batch get dan forma a tus bucles de carga masiva. Consulta operaciones en batch.
- 100 acciones por transacción es el que la gente golpea al intentar hacer que DynamoDB se comporte de forma relacional. Consulta transacciones.
- 20 GSI, 5 LSI, 100 atributos proyectados condicionan el diseño de patrones de acceso mucho más a menudo que las cuotas de rendimiento, y el número de LSI queda fijado en el momento en que se crea la tabla. Consulta proyecciones de índice y GSI frente a LSI.
La mayoría de los rechazos citados arriba también tienen su propia página bajo
errores de DynamoDB, con la solicitud que produce cada uno.
Los cuatro rechazos de CreateTable no la tienen — se capturaron para esta
página.
Para comprobar un solo Item contra el límite de 400 KB sin escribirlo, la calculadora de tamaño de Item corre en tu navegador. Para mirar los Items de tus propias tablas, DynoTable es un cliente de escritorio para DynamoDB.