DynamoDB TTL 完整指南:讓項目自動過期
存留時間(Time to Live,TTL)讓 DynamoDB 在你存在項目上的一個時間戳 過去之後自動刪除它。你指定一個持有 Unix-epoch 到期時間的屬性,然後 DynamoDB 就在背景收割到期的項目 — 沒有收割工作、沒有額外成本。
在那個稽核日誌的情境裡,每個租戶都有一個保留政策:事件保留 90 天、或 1 年、或對合規要求高的租戶保留 7 年。TTL 就是你不必自己跑一趟 刪除掃描就能執行那份政策的方法。
DynamoDB 的 TTL 是怎麼運作的?
DynamoDB TTL 會在你存在一個指定屬性中的 Unix-epoch(秒)時間戳過去之後,自動刪除項目。你在表格上啟用 TTL、指定那個到期屬性,然後 DynamoDB 就在背景收割到期的項目 — 通常在幾天之內,且沒有寫入容量成本。到期的項目在被實體刪除之前仍然可讀。
- TTL 是一個持有 Unix-epoch(秒)時間戳的屬性。 當那個時間 過去,這個項目就符合刪除的資格。
- 刪除是背景且盡力而為的 — 通常在到期後幾天之內,而不是 精確的那一秒。
- TTL 刪除是免費的 — 它們不消耗寫入容量,不過在一個 global table 上,被複寫的刪除在每一個其他複本區域都算一次寫入。
- 已到期但尚未刪除的項目仍會出現在讀取中,所以如果你需要 立即隱藏它們,就在那個到期屬性上做篩選。
問題所在:自己讓舊資料到期很貴
沒有 TTL,執行「丟棄超過 90 天的事件」意味著跑你自己的
收割器:定時掃描(或查詢)舊項目,並對每一個 DeleteItem。
那個掃描燒讀取容量、那些刪除燒寫入容量,而排程、失敗和
重試都歸你負責。
對一個高流量的稽核日誌而言,那是一筆持續、不斷增長、只為了 丟掉資料的稅。TTL 把整份工作移進 DynamoDB,免費。
TTL 如何運作
你在一個表格上啟用 TTL,並告訴它哪個屬性持有到期時間。按照 AWS 的公告, 你指定一個持有 Unix-epoch 到期時間戳的項目屬性,而 DynamoDB 就在背景自動處理刪除,不影響表格 效能。
有兩個屬性對正確性很重要:
- 它是盡力而為,不是精確的。 DynamoDB 在背景掃描到期的項目並 刪除它們;刪除通常發生在到期後幾天之內。一個項目在它的時間戳 就_符合資格_,但可能短暫地滯留。
- 到期的項目在被收割之前仍然可讀。 一個
Query可以回傳一個 TTL 已過但尚未被刪除的項目 — 所以如果「到期=立即不可見」 是一個硬性要求,就在那個到期屬性上加一個FilterExpression。
而且 TTL 刪除不消耗寫入容量,這正是讓它嚴格比一個 自己跑的收割器更便宜的原因。
一個實作範例:每租戶的保留
每一個稽核事件在被寫入時都帶著一個設定好的 expiresAt 屬性 —
現在 + 該租戶的保留窗口,以 epoch 秒計:
| PK | SK | action | expiresAt | note |
|---|---|---|---|---|
| TENANT#acme | EVENT#2026-03-26T…#a0 | login.success | 1782259200 | 90-day tenant: eligible now |
| TENANT#acme | EVENT#2026-06-24T…#a1 | invoice.export | 1790035200 | still inside window |
| TENANT#globex EVENT#2026-06-24T…#b9 | role.granted | 2003184000 | 7-year compliance tenant |
TTL 以 expiresAt 作為 TTL 屬性啟用。當 acme 的 90 天事件
越過 1782259200,DynamoDB 就在大約兩天之內自行刪除它。那個
合規租戶的事件帶著一個遠在未來的 expiresAt,所以它們存活下來 — 同一個
表格、同一套機制、每個項目不同的保留。
寫入端只是在你建立事件時多加一個數字。你可以在
DynamoDB Expression Builder 中組合那個
SET expiresAt = :ttl 子句並驗證那個帶型別的 :ttl 值。
要立即從一次讀取中隱藏一個已到期但未收割的事件,就在查詢的
FilterExpression 上加 expiresAt > :now — 不過記得一個篩選
並不會降低讀取成本(query 與 scan)。
在 DynoTable 中操作
經典的 TTL bug 是一個錯的 expiresAt:以毫秒而非
秒儲存,或以一個 ISO 字串儲存,於是那個項目要嘛永不到期、要嘛
立即消失。抓到它的唯一方法,是去看那個實際儲存的值和
它的型別。
DynoTable 顯示每個項目的屬性連同它們的 DynamoDB 型別,所以你可以
確認 expiresAt 是一個以 epoch _秒_計的 Number — 不是一個 String、不是
毫秒 — 然後才把真正的保留託付給 TTL。

陷阱與後續步驟
- 是 epoch 秒,作為一個 Number。 這是最常見的 TTL 錯誤。一個 毫秒值會把到期推到約 50,000 年後;一個 ISO 字串會被完全 忽略。驗證型別和單位。把值貼進 TTL 轉換器——它會自動偵測秒 與毫秒,而它標出的正是這個錯誤。
- 別依賴刪除的時機。 到期與刪除之間可能過幾天。如果「一 到期就消失」很重要,就在讀取中對那個屬性篩選;別假設那一列 已經實體消失了。
- TTL 刪除會出現在 Streams 中。 一次 TTL 刪除會發出一筆被標記為 系統產生的串流記錄 — 那是在到期事件消失之前把它們歸檔到 S3 的標準掛鉤。見 DynamoDB Streams。
- TTL 刪除也會打到 。 移除一個項目也會把它從它 曾在的任何次要索引裡移除 — 那是預期中的清理,但如果一個索引 驅動了某個計數,這件事就值得知道。
TTL 便宜地處理一個事件生命的終點。下一個問題是你一開始為那些 寫入付了什麼 — On-Demand 與 Provisioned 容量。
下載 DynoTable,在你開啟 TTL 之前,先檢視你項目的屬性 型別,並確認你的 TTL 屬性是一個 Unix-epoch Number。


