DynamoDB TTL
Time to Live(TTL)を使うと、アイテムに保存したタイムスタンプを過ぎた時点でDynamoDBが自動的にそのアイテムを削除します。Unixエポックの有効期限を保持する属性を1つ指定すると、DynamoDBがバックグラウンドで期限切れアイテムを刈り取ります — 刈り取りジョブも追加コストも不要です。
監査ログのシナリオでは、各テナントに保持ポリシーがあります。イベントを90日、または1年、コンプライアンスの厳しいテナントなら7年保持する、といった具合です。TTLは、自前の削除スイープを実行することなくそれを強制する方法です。
DynamoDB TTLはどのように機能しますか?
指定した属性に保存したUnixエポック(秒)のタイムスタンプを過ぎると、DynamoDB TTLはアイテムを自動的に削除します。テーブルでTTLを有効化し、有効期限属性を指定すると、DynamoDBはバックグラウンドで期限切れアイテムを刈り取ります — 通常は48時間以内で、書き込みキャパシティコストはかかりません。期限切れアイテムは物理的に削除されるまで読み取り可能です。
- TTLはUnixエポック(秒)のタイムスタンプを保持する1つの属性です。 その時刻を過ぎると、アイテムは削除の対象になります。
- 削除はバックグラウンドかつベストエフォートです — 通常は有効期限から数日以内で、正確なその秒ではありません。AWSは48時間以内を目標としています。
- TTL削除は無料です — 書き込みキャパシティを消費しません。
- 期限切れだがまだ削除されていないアイテムは依然として読み取りに現れます。即座に隠す必要があるなら、有効期限属性でフィルタリングしてください。
問題:古いデータを自前で期限切れにするのは高くつく
TTLがないと、「90日より古いイベントを削除する」を強制するには自前の刈り取りジョブを実行することになります。スケジュールで古いアイテムをスキャン(またはクエリ)し、それぞれDeleteItemする。そのスキャンは読み取りキャパシティを消費し、削除は書き込みキャパシティを消費し、スケジュール、失敗、リトライをあなたが所有します。
大量の監査ログにとって、それはデータを捨てるためだけの、絶え間なく増え続ける税金です。TTLはこの仕事全体をDynamoDBへ無料で移します。
TTLの仕組み
テーブルでTTLを有効にし、どの属性が有効期限を保持するかを伝えます。AWSの発表によれば、「Unixエポックの有効期限タイムスタンプを含むアイテム属性を指定すると、DynamoDBがテーブルのパフォーマンスに影響を与えることなくバックグラウンドで自動的に削除を処理」します。
正しさのために2つの性質が重要です:
- ベストエフォートであり、正確ではありません。 DynamoDBは期限切れアイテムをスキャンしバックグラウンドで削除します。AWSは有効期限から48時間以内の削除を目標としています。アイテムはそのタイムスタンプで対象になりますが、しばらく残ることがあります。
- 期限切れアイテムは刈り取られるまで読み取り可能です。
QueryはTTLを過ぎたがまだ削除されていないアイテムを返すことがあります — したがって「期限切れ = 即座に不可視」が厳格な要件なら、有効期限属性にFilterExpressionを追加してください。
そしてTTL削除は書き込みキャパシティを消費しません。これが自前の刈り取りジョブより厳密に安い理由です。
実例:テナントごとの保持
各監査イベントは、イベントが書き込まれるときに設定されるexpiresAt属性 — now + テナントの保持ウィンドウをエポック秒で — を持ちます:
| PK | SK | action | expiresAt | note |
|---|---|---|---|---|
| TENANT#acme | EVENT#2026-03-26T…#a0 | login.success | 1758873600 | 90-day tenant: eligible now |
| TENANT#acme | EVENT#2026-06-24T…#a1 | invoice.export | 1766620800 | still inside window |
| TENANT#globex EVENT#2026-06-24T…#b9 | role.granted | 1798156800 | 7-year compliance tenant |
TTLはexpiresAtをTTL属性として有効化されます。acmeの90日イベントが1758873600を越えると、DynamoDBがおおよそ2日以内に自動でそれを削除します。コンプライアンステナントのイベントははるか未来のexpiresAtを持つので残ります — 同じテーブル、同じ仕組み、アイテムごとに異なる保持です。
書き込み側は、イベントを作成するときに数値を1つ追加するだけです。SET expiresAt = :ttl句を組み立て、型付きの:ttl値をDynamoDB Expression Builderで検証できます。
期限切れだが未刈り取りのイベントを読み取りから即座に隠すには、クエリのFilterExpressionにexpiresAt > :nowを追加します — ただしフィルタは読み取りコストを減らさないことを覚えておいてください(QueryとScanの比較)。
DynoTableでの実践
典型的なTTLのバグは、誤ったexpiresAtです。秒ではなくミリ秒で保存されていたり、ISO文字列だったりして、アイテムが決して期限切れにならないか、即座に消えてしまうかのどちらかになります。これを捕まえる唯一の方法は、実際に保存された値とその型を見ることです。
DynoTableは各アイテムの属性をそのDynamoDB型とともに表示するので、実際の保持でTTLを信頼する前に、expiresAtがエポック秒のNumberであること — Stringでもミリ秒でもないこと — を確認できます。

落とし穴と次のステップ
- エポック秒で、Numberとして。 これは最も多いTTLの間違いです。ミリ秒値は有効期限を約5万年先へ押しやり、ISO文字列は完全に無視されます。型と単位を検証してください。
- 削除のタイミングに依存しないでください。 有効期限から削除まで最大約48時間が経過することがあります。「期限切れの瞬間に消える」ことが重要なら、読み取りで属性をフィルタリングしてください。行が物理的に消えたと仮定しないでください。
- TTL削除はStreamsに現れます。 TTL削除はシステム生成としてフラグ付けされたストリームレコードを発行します — これは期限切れイベントが消える前にS3へアーカイブする標準的なフックです。DynamoDB Streamsを参照してください。
- TTL削除はGSIにも作用します。 アイテムの削除は、それが含まれていたあらゆるセカンダリインデックスからも削除します — これは意図したクリーンアップですが、インデックスがカウントを支えていた場合は知っておく価値があります。
TTLはイベントのライフサイクルの終わりを安価に処理します。次の問いは、そもそもその書き込みに何を支払うか — オンデマンドとプロビジョンドキャパシティの比較です。
TTLをオンにする前にアイテムの属性型を確認し、TTL属性がUnixエポックのNumberであることを確かめるには、DynoTableをダウンロードしてください。


