DynamoDB TTL 完整指南:让数据项自动过期
存活时间(TTL)让 DynamoDB 在你存储在项上的一个时间戳 过去之后自动删除该项。你指定一个保存 Unix 纪元过期时间的属性, DynamoDB 就会在后台清理过期的项 —— 无清理作业,无额外成本。
在审计日志的场景里,每个租户都有一份保留策略:把事件保留 90 天、或 1 年、对合规要求重的租户则保留 7 年。TTL 就是你在 不运行自己的删除扫描的情况下强制执行它的方式。
DynamoDB TTL 是如何工作的?
DynamoDB TTL 在你存储在一个指定属性里的 Unix 纪元(秒)时间戳过去之后,自动删除项。你在表上启用 TTL、指定那个过期属性,DynamoDB 就会在后台清理过期的项 —— 通常在几天之内,且不产生写入容量成本。过期的项在被物理删除之前仍然可读。
- TTL 是一个保存 Unix 纪元(秒)时间戳的属性。 当那个时间 过去,该项就有资格被删除。
- 删除是后台的、尽力而为的 —— 通常在过期后的几天之内, 而不是精确的那一秒。
- TTL 删除是免费的 —— 它们不消耗写入容量,尽管在一张全局 表上,被复制的删除会在其他每个副本区域各花一次写入。
- 过期但尚未删除的项仍会出现在读取里,所以如果你需要立即 隐藏它们,就在过期属性上过滤。
问题:自己过期旧数据很昂贵
没有 TTL,强制执行"丢弃 90 天以上的事件"意味着运行你自己的
清理器:定时扫描(或查询)旧项,并对每一个 DeleteItem。
那次扫描烧掉读取容量,那些删除烧掉写入容量,而且你要自己承担
调度、失败和重试。
对于一个高流量的审计日志,那是一笔为了扔掉数据而持续、 不断增长的税。TTL 把整个活儿搬进 DynamoDB,免费。
TTL 是如何运作的
你在一张表上启用 TTL,并告诉它哪个属性保存过期时间。按 AWS 公告 所述,你指定一个保存 Unix 纪元过期时间戳的项属性, DynamoDB 就会在后台自动处理删除,而不影响表 性能。
有两个属性对正确性至关重要:
- 它是尽力而为的,不是精确的。 DynamoDB 扫描过期的项并在 后台删除它们;删除通常在过期后的几天之内发生。一个项在其 时间戳处_有资格_被删,但可能短暂滞留。
- 过期的项在被清理前仍然可读。 一次
Query可以返回一个 TTL 已过但尚未被删除的项 —— 所以如果"过期 = 立即不可见" 是一个硬性要求,就在过期属性上加一个FilterExpression。
而 TTL 删除不消耗写入容量,这正是让它严格比自运行的 清理器更廉价的原因。
一个完整示例:按租户的保留
每个审计事件都携带一个在事件写入时设置的 expiresAt 属性 ——
当前时间 + 该租户的保留窗口,以纪元秒计:
| 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 表达式构建器里
组合那个 SET expiresAt = :ttl 子句并验证带类型的 :ttl 值。
要立即从一次读取里隐藏一个过期但未清理的事件,就往查询的
FilterExpression 里加 expiresAt > :now —— 不过记住一个过滤器
不会减少读取成本(query 与 scan 对比)。
在 DynoTable 中操作
经典的 TTL bug 是一个错误的 expiresAt:以毫秒而不是
秒存储,或者存成一个 ISO 字符串,导致这个项要么永不过期,要么立即
消失。抓住它的唯一办法就是查看实际存储的值和
它的类型。
DynoTable 显示每个项的属性及其 DynamoDB 类型,这样你就能
确认 expiresAt 是一个纪元_秒_的 Number —— 不是 String,也不是
毫秒 —— 然后再放心把真实的保留托付给 TTL。

陷阱与后续步骤
- 纪元秒,作为一个 Number。 这是最常见的 TTL 错误。一个 毫秒值会把过期推到约 50,000 年之后;一个 ISO 字符串则被 完全忽略。验证类型和单位。把值粘贴进 TTL 转换器——它会自动检测秒与毫秒,并恰好标记出这个错误。
- 别依赖删除的时机。 从过期到删除之间可能过去 几天。如果"过期即消失"很要紧,就在读取时在该属性上 过滤;别假设那一行已经被物理删除。
- TTL 删除会出现在 Streams 里。 一次 TTL 删除会发出一条被标记为 系统生成的流记录 —— 这是归档过期事件到 S3 的标准 钩子,趁它们消失之前。参见 DynamoDB Streams。
- TTL 删除同样命中 。 移除一个项也会把它从它所在的任何 二级索引里移除 —— 这是预期中的清理,但如果某个索引驱动了 一个计数,那就值得留意。
TTL 廉价地处理一个事件生命的终点。下一个问题是你一开始为 那些写入付了多少 —— 按需容量与预置容量对比。
下载 DynoTable,在你打开 TTL 之前,检视你各项的属性 类型,确认你的 TTL 属性是一个 Unix 纪元 Number。


