中級読了 1 分

DynamoDB TTL 完全ガイド:アイテムの有効期限

Time to Live(TTL) は、あなたがアイテムに保存したタイムスタンプが過ぎると、DynamoDB がそのアイテムを 自動的に削除できるようにします。Unix エポックの有効期限を保持する1つの属性を指定すると、DynamoDB は 期限切れのアイテムをバックグラウンドで刈り取ります — 刈り取りジョブも、追加コストもありません。

監査ログのシナリオでは、各テナントに保持ポリシーがあります。イベントを90日間、あるいは1年間、あるいは コンプライアンス重視のものなら7年間保持する、というように。TTL は、自前の削除スイープを走らせることなく、 それを強制する方法です。

DynamoDB TTL はどのように機能するのか?

DynamoDB TTL は、あなたが指定した属性に保存する Unix エポック(秒)のタイムスタンプが過ぎると、アイテムを 自動削除します。テーブルで TTL を有効にし、有効期限の属性を指定すると、DynamoDB は期限切れのアイテムを バックグラウンドで刈り取ります — 通常は数日以内で、書き込みキャパシティのコストはかかりません。期限切れの アイテムは、物理的に削除されるまで読み取り可能なままです。

  • TTL は Unix エポック(秒)のタイムスタンプを保持する1つの属性。 その時刻が過ぎると、アイテムは削除の 対象になります。
  • 削除はバックグラウンドかつベストエフォート — 通常は期限切れから数日以内であって、正確な秒ではありません。
  • TTL の削除は無料 — 書き込みキャパシティを消費しません。ただし、グローバルテーブルでは、複製された削除が 他のすべてのレプリカリージョンで書き込み分のコストがかかります。
  • 期限切れだがまだ削除されていないアイテムは依然として現れるので、すぐに隠したい場合は有効期限の属性で フィルタリングしましょう。

問題: 古いデータを自前で期限切れにするのは高コスト

TTL がないと、「90日より古いイベントを削除する」を強制するには、自前の刈り取りを走らせることになります。 スケジュールで古いアイテムをスキャン(またはクエリ)し、それぞれを DeleteItem します。そのスキャンは 読み取りキャパシティを消費し、削除は書き込みキャパシティを消費し、そしてスケジュール、失敗、再試行を あなたが所有します。

大量の監査ログにとって、それはデータを捨てるためだけの、絶え間なく増大する税金です。TTL は、その仕事全体を DynamoDB へ、無料で移します。

TTL の仕組み

テーブルで TTL を有効にし、どの属性が有効期限を保持するかを伝えます。 AWS の発表 によれば、Unix エポックの有効期限タイムスタンプを保持するアイテム属性を指定すると、DynamoDB がテーブルの パフォーマンスに影響を与えることなく、バックグラウンドで自動的に削除を処理します。

正確性のために2つの特性が重要です。

  • ベストエフォートであって、正確ではない。 DynamoDB は期限切れのアイテムをスキャンしてバックグラウンドで 削除します。削除は通常、期限切れから数日以内に起こります。アイテムはそのタイムスタンプで 対象になります が、 短時間残ることがあります。
  • 期限切れのアイテムは刈り取られるまで依然として読み取り可能。 Query は、TTL が過ぎたがまだ削除されて いないアイテムを返すことがあります — なので、「期限切れ = 即座に不可視」が絶対要件なら、有効期限の属性に FilterExpression を追加しましょう。

そして TTL の削除は書き込みキャパシティを消費しません。これが、自前の刈り取りより厳密に安価である理由です。

実例: テナントごとの保持

各監査イベントは、イベントが書き込まれたときに設定される expiresAt 属性を運びます — now + テナントの保持ウィンドウ、エポック秒で。

PKSKactionexpiresAtnote
TENANT#acmeEVENT#2026-03-26T…#a0login.success178225920090-day tenant: eligible now
TENANT#acmeEVENT#2026-06-24T…#a1invoice.export1790035200still inside window
TENANT#globex EVENT#2026-06-24T…#b9role.granted20031840007-year compliance tenant

TTL は expiresAt を TTL 属性として有効にされています。acme の90日イベントが 1782259200 を越えると、 DynamoDB はおよそ2日以内にひとりでにそれを削除します。コンプライアンステナントのイベントは遥か未来の expiresAt を運ぶので、生き残ります — 同じテーブル、同じ仕組み、アイテムごとに異なる保持です。

書き込み側は、イベントを作成するときに1つの数値を追加するだけです。SET expiresAt = :ttl 句を組み立て、 型付きの :ttl 値を DynamoDB 式ビルダー で検証できます。

期限切れだが刈り取られていないイベントを読み取りから即座に隠すには、クエリの FilterExpressionexpiresAt > :now を追加します — ただし、フィルターは読み取りコストを減らさないことを思い出してください (query 対 scan)。

DynoTable でやってみる

古典的な TTL のバグは、間違った expiresAt です。秒の代わりにミリ秒で、あるいは ISO 文字列として 保存されていると、アイテムは決して期限切れにならないか、即座に消え去ります。それを捕まえる唯一の方法は、 実際に保存された値とその型を見ることです。

DynoTable は各アイテムの属性を DynamoDB の型とともに表示するので、expiresAt がエポック の Number で あること — String でも、ミリ秒でもないこと — を、実際の保持を TTL に託す前に確認できます。

DynoTable で監査イベントの expiresAt 属性が Unix エポック秒の Number であること — TTL が作用する唯一の値 — を検証する様子。
DynoTable で監査イベントの expiresAt 属性が Unix エポック秒の Number であること — TTL が作用する唯一の値 — を検証する様子。

落とし穴と次のステップ

  • エポック秒、Number として。 これは最も一般的な TTL のミスです。ミリ秒の値は有効期限を約5万年先へ 押しやり、ISO 文字列は完全に無視されます。型と単位を検証しましょう。値を TTL コンバーターに貼り付けてください — 秒とミリ秒を 自動検出し、まさにこのミスを指摘します。
  • 削除のタイミングに頼らない。 期限切れと削除の間に数日が経つことがあります。「期限切れの瞬間に消える」が 重要なら、読み取りで属性をフィルタリングしましょう。行が物理的に消えたと仮定してはいけません。
  • TTL の削除は Streams に現れる。 TTL の削除は、システム生成としてフラグが立ったストリームレコードを 発します — 期限切れのイベントが消える前に S3 へアーカイブする標準的なフックです。 DynamoDB Streamsを参照してください。
  • TTL の削除は にも及ぶ。 アイテムを削除すると、それが入っていた任意のセカンダリインデックスからも 削除されます — これは意図されたクリーンアップですが、インデックスがカウントを駆動していた場合は知っておく 価値があります。

TTL はイベントのライフサイクルの終わりを安価に処理します。次の疑問は、そもそも書き込みに何を支払うのか — オンデマンド対プロビジョンドキャパシティ — です。

DynoTable をダウンロード して、アイテムの属性の型を検査し、TTL をオンにする前に、TTL 属性が Unix エポックの Number であることを確認しましょう。

更新日