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

  1. Intercettalo e ri-inizializza l'iterator dal tuo ultimo checkpoint — tieni traccia del SequenceNumber dell'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_HORIZON rielabora lo shard dal record disponibile più vecchio; LATEST salta all'attività nuova.

  2. Fai il checkpoint dei sequence number, mai degli iterator — il sequence number è il punto di ripresa durevole.

  3. Mantieni stretto il loop di poll — svolgi il lavoro pesante per-record in modo asincrono (mettilo in coda) così la cadenza di GetRecords resta ben dentro i 15 minuti.

  4. Preferisci consumer gestiti — le event source mapping di Lambda e il DynamoDB Streams Kinesis Adapter (KCL) gestiscono iterator e checkpoint per te; i loop GetRecords fatti 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

References

Ultima verifica 2026-07-13 rispetto alla documentazione ufficiale AWS collegata sopra.

Lavora con DynamoDB senza la Console

DynoTable è un client desktop veloce per DynamoDB — sfoglia le tabelle, esegui query in stile SQL e modifica gli Item localmente.