DynamoDB Streams: ExpiredIteratorException
In breve — Uno shard iterator ottenuto da GetShardIterator è valido solo per 15 minuti. Se il tuo consumer si è messo in pausa, ha elaborato un batch lentamente, o ha trattenuto un iterator attraverso un riavvio, la successiva chiamata GetRecords genera questo. Recupera richiedendo un nuovo iterator — usa AFTER_SEQUENCE_NUMBER con l'ultimo sequence number che hai elaborato così riprendi esattamente da dove ti eri fermato.
Cosa significa
ExpiredIteratorException: The provided iterator exceeds the maximum age allowed.Leggere uno stream DynamoDB direttamente è un loop in due passaggi: GetShardIterator ti dà un handle di posizione in uno shard, e ogni chiamata GetRecords lo consuma e restituisce il successivo (NextShardIterator). Ognuno di questi handle scade 15 minuti dopo essere stato emesso. L'eccezione non significa che i dati siano andati persi — i record dello stream vivono per 24 ore — significa solo che questo handle di posizione è obsoleto e te ne serve uno nuovo.
Perché accade
- Elaborazione lenta tra i poll — il lavoro svolto per batch (scritture, chiamate esterne) richiede più di 15 minuti prima del successivo
GetRecords. - Un consumer in pausa o sospeso — un worker fermato, un deploy lungo, o una sessione di debugger che trattiene il loop.
- Memorizzazione degli iterator — persistere la stringa dell'iterator (in un DB o checkpoint) e riutilizzarla più tardi; gli iterator sono effimeri, i sequence number no.
- Backoff andato per le lunghe — un loop di retry su errore che ha dormito oltre la finestra.
Come correggerlo
Intercettalo e ri-inizializza l'iterator dal tuo ultimo checkpoint — tieni traccia del
SequenceNumberdell'ultimo record che hai elaborato, poi:const {ShardIterator} = await streams.send( new GetShardIteratorCommand({ StreamArn: streamArn, ShardId: shardId, ShardIteratorType: 'AFTER_SEQUENCE_NUMBER', SequenceNumber: lastProcessedSequenceNumber }) );Nessun checkpoint ancora?
TRIM_HORIZONrielabora lo shard dal record disponibile più vecchio;LATESTsalta all'attività nuova.Fai il checkpoint dei sequence number, mai degli iterator — il sequence number è il punto di ripresa durevole.
Mantieni stretto il loop di poll — svolgi il lavoro pesante per-record in modo asincrono (mettilo in coda) così la cadenza di
GetRecordsresta ben dentro i 15 minuti.Preferisci consumer gestiti — le event source mapping di Lambda e il DynamoDB Streams Kinesis Adapter (KCL) gestiscono iterator e checkpoint per te; i loop
GetRecordsfatti a mano sono dove vive questa eccezione.
Assicurati che la tua gestione sia idempotente: riprendere da un checkpoint può riconsegnare un record che avevi elaborato a metà. Lo stream stesso contiene ogni record esattamente una volta, ma un consumer che si ri-inizializza dal suo ultimo checkpoint elabora di fatto at-least-once.
Fare il debug di ciò che uno stream ha effettivamente emesso è molto più facile quando puoi vedere gli Item cambiare — l'app desktop DynoTable mostra lo stato live di un Item così puoi confrontare i record dello stream con i dati. Stai stimando il costo di lettura di un replay di recupero? Il calcolatore dei prezzi DynamoDB ti copre.
Errori correlati
- TrimmedDataAccessException — sei rimasto indietro rispetto alla finestra di ritenzione di 24 ore (dati effettivamente persi).
- Stream not enabled
- Invalid StreamArn
- Impara: DynamoDB Streams
References
- GetShardIterator — Amazon DynamoDB Streams API Reference
- GetRecords — Amazon DynamoDB Streams API Reference
- Change data capture for DynamoDB Streams — Amazon DynamoDB Developer Guide
Ultima verifica 2026-07-13 rispetto alla documentazione ufficiale AWS collegata sopra.