DynamoDB Streams: ExpiredIteratorException

TL;DR — GetShardIterator からのシャードイテレーターは 15分間 のみ有効です。コンシューマーが一時停止した、バッチの処理が遅かった、または再起動をまたいでイテレーターを保持した場合、次の GetRecords 呼び出しでこれがスローされます。新しいイテレーターを要求して回復します。最後に処理したシーケンス番号とともに AFTER_SEQUENCE_NUMBER を使えば、中断したまさにその場所から再開できます。

意味

ExpiredIteratorException: The provided iterator exceeds the maximum age allowed.

DynamoDB ストリームを直接読むのは2ステップのループです。GetShardIterator はシャード内の位置ハンドルを与え、各 GetRecords 呼び出しはそれを消費して次のもの(NextShardIterator)を返します。それらのハンドルはすべて、発行後15分で期限切れになります。この例外はデータが消えたことを意味しません。ストリームレコードは24時間存続します。単にこの 位置ハンドル が古くなり、新しいものが必要なことを意味するだけです。

発生する理由

  • ポーリング間の処理が遅い — バッチごとの作業(書き込み、外部呼び出し)が、次の GetRecords までの15分より長くかかる。
  • 一時停止または中断したコンシューマー — 停止したワーカー、長いデプロイ、またはループを保持するデバッガーセッション。
  • イテレーターの保存 — イテレーター文字列を(DB やチェックポイントに)永続化して後で再利用する。イテレーターは一時的で、シーケンス番号はそうではありません。
  • バックオフが長くなりすぎた — ウィンドウを過ぎて眠ったエラーリトライループ。

修正方法

  1. キャッチし、最後のチェックポイントからイテレーターを再シードします — 最後に処理したレコードの SequenceNumber を追跡し、それから:

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

    まだチェックポイントがありませんか?TRIM_HORIZON は利用可能な最も古いレコードからシャードを再処理します。LATEST は新しいアクティビティにスキップします。

  2. イテレーターではなくシーケンス番号をチェックポイントします — シーケンス番号が耐久性のある再開ポイントです。

  3. ポーリングループをタイトに保ちます — レコードごとの重い作業を非同期に行い(キューに入れる)、GetRecords のペースが15分の十分内側にとどまるようにします。

  4. マネージドコンシューマーを優先します — Lambda イベントソースマッピングと DynamoDB Streams Kinesis Adapter(KCL)はイテレーターとチェックポイントを管理してくれます。手作りの GetRecords ループこそがこの例外が住む場所です。

処理が冪等であることを確認してください: チェックポイントからの再開は、途中まで処理したレコードを再配信することがあります。ストリーム自体は各レコードを正確に1回含みますが、最後のチェックポイントから再シードするコンシューマーは実質的に at-least-once で処理します。

ストリームが実際に何を出力したかをデバッグするのは、アイテムが変化するのを見られるとはるかに簡単です。DynoTable デスクトップアプリ はアイテムのライブ状態を表示するため、ストリームレコードをデータと照合できます。キャッチアップリプレイの読み取りコストを見積もりますか?DynamoDB 料金計算ツール がお役に立ちます。

関連するエラー

References

最終検証日 2026-07-13、上記にリンクした公式 AWS ドキュメントに照らして確認しました。

Console なしで DynamoDB を扱う

DynoTable は DynamoDB 向けの高速なデスクトップクライアントです — テーブルを閲覧し、SQL スタイルのクエリを実行し、アイテムをローカルで編集できます。