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
Captúrala y re-siembra el iterador desde tu último checkpoint — registra el
SequenceNumberdel ú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_HORIZONreprocesa el shard desde el registro más antiguo disponible;LATESTsalta a la actividad nueva.Registra números de secuencia, nunca iteradores — el número de secuencia es el punto de reanudación duradero.
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
GetRecordsse mantenga bien dentro de los 15 minutos.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
GetRecordshechos 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
- TrimmedDataAccessException — te quedaste por detrás de la ventana de retención de 24 horas (datos realmente perdidos).
- Stream not enabled
- Invalid StreamArn
- Aprende: DynamoDB Streams
Referencias
- GetShardIterator — Amazon DynamoDB Streams API Reference
- GetRecords — Amazon DynamoDB Streams API Reference
- Change data capture for DynamoDB Streams — Amazon DynamoDB Developer Guide
Verificado por última vez el 2026-07-13 contra la documentación oficial de AWS enlazada arriba.