DynamoDB Streams: ExpiredIteratorException

TL;DR — Un iterador de shard de GetShardIterator solo es válido durante 15 minutos. Si tu consumidor se pausó, procesó un lote lentamente o mantuvo un iterador a través de un reinicio, la siguiente llamada a GetRecords lanza esto. Recupérate solicitando un iterador nuevo — usa AFTER_SEQUENCE_NUMBER con el último número de secuencia que procesaste para reanudar exactamente donde lo dejaste.

Qué significa

ExpiredIteratorException: The provided iterator exceeds the maximum age allowed.

Leer un stream de DynamoDB directamente es un bucle de dos pasos: GetShardIterator te da un manejador de posición en un shard, y cada llamada a GetRecords lo consume y devuelve el siguiente (NextShardIterator). Cada uno de esos manejadores caduca 15 minutos después de emitirse. La excepción no significa que los datos hayan desaparecido — los registros del stream viven 24 horas — solo significa que este manejador de posición está obsoleto y necesitas uno nuevo.

Por qué ocurre

  • Procesamiento lento entre sondeos — el trabajo hecho por lote (escrituras, llamadas externas) tarda más de 15 minutos antes del siguiente GetRecords.
  • Un consumidor pausado o suspendido — un worker detenido, un deploy largo o una sesión de depurador que retiene el bucle.
  • Almacenar iteradores — persistir la cadena del iterador (en una BD o checkpoint) y reutilizarla más tarde; los iteradores son efímeros, los números de secuencia no.
  • Un backoff demasiado largo — un bucle de reintento por error que durmió más allá de la ventana.

Cómo solucionarlo

  1. Captúrala y re-siembra el iterador desde tu último checkpoint — registra el SequenceNumber del último registro que procesaste, luego:

    const {ShardIterator} = await streams.send(
      new GetShardIteratorCommand({
        StreamArn: streamArn,
        ShardId: shardId,
        ShardIteratorType: 'AFTER_SEQUENCE_NUMBER',
        SequenceNumber: lastProcessedSequenceNumber
      })
    );

    ¿Aún sin checkpoint? TRIM_HORIZON reprocesa el shard desde el registro más antiguo disponible; LATEST salta a la actividad nueva.

  2. Registra números de secuencia, nunca iteradores — el número de secuencia es el punto de reanudación duradero.

  3. Mantén el bucle de sondeo ceñido — haz el trabajo pesado por registro de forma asíncrona (encolándolo) para que la cadencia de GetRecords se mantenga bien dentro de los 15 minutos.

  4. Prefiere consumidores gestionados — los event source mappings de Lambda y el DynamoDB Streams Kinesis Adapter (KCL) gestionan iteradores y checkpoints por ti; los bucles de GetRecords hechos a mano son donde vive esta excepción.

Asegúrate de que tu manejo sea idempotente: reanudar desde un checkpoint puede reentregar un registro que procesaste a medias. El stream en sí contiene cada registro exactamente una vez, pero un consumidor que re-siembra desde su último checkpoint procesa efectivamente al menos una vez.

Depurar lo que un stream realmente emitió es mucho más fácil cuando puedes ver los Items cambiando — la aplicación de escritorio DynoTable muestra el estado en vivo de un Item para que cotejes los registros del stream contra los datos. ¿Estimando el coste de lectura de una reproducción de puesta al día? La calculadora de precios de DynamoDB te cubre.

Errores relacionados

Referencias

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

Trabaja con DynamoDB sin la Consola

DynoTable es un cliente de escritorio rápido para DynamoDB: explora tablas, ejecuta consultas estilo SQL y edita Items localmente.