Diseño de tabla única en DynamoDB
Viniendo de SQL, el instinto es una tabla por entidad: customers, orders,
order_items. En DynamoDB ese instinto suele estar equivocado. Una única tabla que
almacena todas las entidades, distinguidas por prefijos de clave sobrecargados,
te permite obtener un padre y sus hijos en un Query —sin joins, sin N+1.
Empieza por los patrones de acceso, no por las entidades
El diseño de tabla única es lo primero el patrón de acceso. Antes de elegir una
única clave, escribe cada lectura que hace tu aplicación —«obtener el perfil de un
cliente», «listar los pedidos de un cliente de más nuevo a más antiguo», «encontrar
todos los pedidos abiertos»— porque las claves existen solo para servir esa lista.
La normalización relacional optimiza el almacenamiento; el modelado de DynamoDB
optimiza las consultas que ya sabes que vas a ejecutar. Enuméralas y luego diseña
las claves para que cada una sea un único Query.
La idea
Elige nombres de clave genéricos (PK, SK) y codifica el tipo de entidad en el
valor:
| PK | SK | attributes |
|---|---|---|
| CUSTOMER#42 | PROFILE | name, email, plan |
| CUSTOMER#42 | ORDER#2026-001 | total, status |
| CUSTOMER#42 | ORDER#2026-002 | total, status |
Ahora un Query PK = "CUSTOMER#42" devuelve el perfil y todos los pedidos en
una sola lectura facturada. SK begins_with "ORDER#" lo acota solo a los pedidos.
Visualmente, los Items sobrecargados se apilan bajo una única clave de partición como una sola colección de Items:
Una sola lectura de la partición te devuelve el cliente y todos los pedidos juntos.
GSI sobrecargados
El mismo truco funciona en los índices. Pon un GSI1PK/GSI1SK genérico en los
Items, y un único GSI sirve a múltiples patrones de acceso según lo que cada Item
escriba en esos atributos:
| PK | SK | GSI1PK | GSI1SK |
|---|---|---|---|
| ORDER#001 | METADATA | STATUS#OPEN | 2026-01-04 |
| ORDER#002 | METADATA | STATUS#OPEN | 2026-01-05 |
Ahora Query GSI1 WHERE GSI1PK = "STATUS#OPEN" lista los pedidos abiertos por fecha
—un patrón que la tabla base no puede responder. Una entidad diferente puede
reutilizar GSI1 con su propio significado (p. ej. CATEGORY#books). Un índice,
muchas consultas.
Muchos a muchos: la lista de adyacencia
Para las relaciones (un usuario en muchos equipos, un equipo con muchos usuarios),
escribe la arista dos veces con los ids intercambiados: PK=USER#1, SK=TEAM#9
y PK=TEAM#9, SK=USER#1. Consultar cualquiera de los dos lados lista el otro —el
sustituto de DynamoDB para una tabla de join.
Cuándo no usar tabla única
No es gratis. Una tabla sobrecargada es más difícil de razonar, más difícil de evolucionar y hostil a la analítica. Si tus patrones de acceso son genuinamente desconocidos o cambian constantemente, o si los datos son mayormente analíticos, tablas separadas (u otro almacén) pueden ser la decisión más sensata. La tabla única gana cuando los patrones son conocidos y de alto volumen.
El coste de la forma equivocada
Modelar como tablas separadas obliga a un Scan o a un join en el lado del cliente
para reensamblar un cliente, y ese es el footgun del Scan.
Modela primero los patrones de acceso y luego diseña las claves para que cada uno
sea un Query.
Estima lo que cuestan estos Items por lectura con la calculadora de tamaño de Items y capacidad, y prueba DynoTable para explorar un schema de tabla única y ver las colecciones sobrecargadas en paralelo.