DynamoDB BatchGetItem en Node.js (AWS SDK v3)

BatchGetItem recupera hasta 100 Items por clave primaria en una sola petición. En el AWS SDK v3 la llamada tiene que ser un bucle, porque UnprocessedKeys llega en una respuesta correcta y no como error. Qué lo rellena, y por qué 16 MB y 1 MB por partición son las cifras que importan, lo cubre operaciones por lotes en DynamoDB. Esta página trata de la llamada de v3 y de lo que te devuelve.

Código

import {BatchGetItemCommand, DynamoDBClient} from '@aws-sdk/client-dynamodb';

const client = new DynamoDBClient({region: 'us-east-1'});

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

let requestItems = {
  Music: {
    Keys: [
      {Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'Cubano Chant'}},
      {Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'A Mis Abuelos'}},
      {Artist: {S: 'Ella Fitzgerald'}, SongTitle: {S: 'Misty'}}
    ]
  }
};

const items = [];
let attempt = 0;

do {
  const response = await client.send(new BatchGetItemCommand({RequestItems: requestItems}));
  items.push(...(response.Responses?.Music ?? []));

  // A partial result is NOT an error: throttling, a >16 MB response, or an
  // internal failure returns the leftovers in UnprocessedKeys. Retry them
  // with exponential backoff.
  requestItems = response.UnprocessedKeys;
  if (requestItems && Object.keys(requestItems).length > 0) {
    attempt += 1;
    await sleep(Math.min(100 * 2 ** attempt, 5000));
  }
} while (requestItems && Object.keys(requestItems).length > 0);

console.log(`Fetched ${items.length} items`);

Explicación

  • El encadenamiento opcional no es ruido defensivo. Responses y UnprocessedKeys son ambos opcionales en los tipos de v3, así que response.Responses?.Music ?? [] y la guarda con Object.keys() son justo lo que pide el compilador. En JavaScript plano son lo que evita que la primera respuesta vacía lance un error.
  • Ramifica según err.name. v3 pone ahí el código de error del servicio, y los dos fallos que esta operación realmente lanza no son reintentables, así que nunca deben caer en el bucle de backoff. Más de 100 claves da ValidationException / Too many items requested for the BatchGetItem call; la misma clave dos veces da Provided list of item keys contains duplicates. Ambos están reproducidos literalmente en la página de Python.
  • UnprocessedKeys llega ya con la forma de RequestItems, que es la única razón por la que el bucle puede reasignarlo directamente. No es un cursor de paginación y no significa que la llamada haya fallado.
  • El backoff es una instrucción de AWS, no un detalle amable. La referencia de la API te dice que uses "an exponential backoff algorithm" porque un reintento inmediato aterriza en la misma partición limitada.
  • ConsistentRead y ProjectionExpression son por tabla, se ponen dentro de cada entrada de RequestItems y no en el nivel superior. Es fácil pasarlo por alto cuando el mapa tiene una sola clave y parece una petición plana.

Qué devuelve realmente la respuesta

Ejecuta el bloque de arriba contra DynamoDB Local 3.3.0 con las tres canciones presentes, añade ReturnConsumedCapacity: 'TOTAL' y registra los títulos en vez del recuento:

order:            [ 'A Mis Abuelos', 'Misty', 'Cubano Chant' ]
UnprocessedKeys:  {}
ConsumedCapacity: [ { TableName: 'Music', CapacityUnits: 1.5 } ]

La petición listaba Cubano Chant, A Mis Abuelos, Misty. La respuesta no está en ninguna de esas posiciones, y por eso el bucle acumula en un array plano en lugar de indexar por desplazamiento. Empareja los Items con las peticiones por sus atributos de clave, e incluye esas claves en cualquier ProjectionExpression para que te quede algo con lo que emparejar.

Pon ConsistentRead: true en esa misma entrada Music y las mismas tres claves cuestan 3 unidades en vez de 1,5. Tres Items de menos de 4 KB cada uno se facturan como tres lecturas GetItem independientes, a media unidad con consistencia eventual y una unidad entera con consistencia fuerte. La calculadora de precios convierte esa aritmética por Item en una cifra mensual antes de que te comprometas con un patrón de lectura.

Ahora borra Misty y vuelve a ejecutarlo: dos Items, un UnprocessedKeys vacío y 1,0 unidades. La clave que faltaba no se facturó. Eso es un artefacto de DynamoDB Local y no el contrato; la referencia de BatchGetItem (consultada el 2026-07-28) dice que las peticiones de Items inexistentes consumen la capacidad de lectura mínima según el tipo de lectura. No dimensiones un lote de fallos de caché a partir de una ejecución local.

Para traerte un conjunto de claves y ver qué devolvió realmente, sin escribir antes el bucle, descarga DynoTable.

Ejemplos relacionados

Referencias

Verificado por última vez el 2026-07-28 contra la documentación oficial de AWS enlazada arriba.

Trabaja con DynamoDB sin la Consola

Un cliente de escritorio rápido para DynamoDB que ejecuta el SQL real que DynamoDB no puede — JOINs, GROUP BY, agregaciones — con edición visual y un agente de IA con tus propias claves de Bedrock.

Prueba gratuita de 30 días, sin tarjeta — después, el plan Free sin límite de tiempo.