Working with TTL Indexes
1. Creating TTL Index
| Aspect | Detail |
|---|---|
| Single field | Must index a Date field (or array of Dates) |
| Option | { expireAfterSeconds: N } |
db.sessions.createIndex({ lastActive: 1 }, { expireAfterSeconds: 1800 });
2. Setting Expiration Time
| Pattern | Form |
|---|---|
| Fixed lifetime | expireAfterSeconds: 86400 |
| Explicit timestamp | expireAfterSeconds: 0 + per-doc Date |
3. Understanding TTL Monitor Thread
| Aspect | Detail |
|---|---|
| Interval | 60 seconds default |
| Throttled | Yes, to avoid impacting workload |
| Latency | Expiration may lag actual deadline by minutes |
4. Using Date Fields for Expiration
| Value | Behavior |
|---|---|
| BSON Date | Deletion triggered after expireAfterSeconds beyond date |
| Array of Dates | Earliest date used |
| Non-Date | Document is not expired |
5. Modifying TTL Index
| Command | Effect |
|---|---|
collMod({index:{name:"idx", expireAfterSeconds: N}}) | Update interval |
| Drop+recreate | Alternative |
6. Removing TTL Behavior
| Approach | Effect |
|---|---|
| Drop index | Removes expiration entirely |
| collMod expireAfterSeconds=Very large | Effectively disable |
7. Monitoring TTL Deletions
| Metric | Source |
|---|---|
| ttl.deletedDocuments | db.serverStatus().metrics.ttl |
| ttl.passes | Sweep cycles count |
8. Understanding TTL Limitations
| Limitation | Detail |
|---|---|
| Capped | Not supported on capped collections |
| Compound | Cannot be compound (single-field only) |
| Precision | Not real-time; ~60s sweep |
| Time series | Use expireAfterSeconds on collection instead |
9. Using TTL with Partial Indexes
| Aspect | Detail |
|---|---|
| Combine | TTL + partialFilterExpression |
| Use case | Expire only "soft-deleted" docs |
db.posts.createIndex(
{ deletedAt: 1 },
{ expireAfterSeconds: 0, partialFilterExpression: { deletedAt: { $exists: true } } }
);
10. Implementing Data Retention Policies
| Policy | Approach |
|---|---|
| Sessions (30 min idle) | TTL on lastActive |
| Logs (90 days) | TTL on createdAt; expireAfterSeconds: 7776000 |
| GDPR cooldown | Soft delete + partial TTL |
| Compliance archive | $merge to cold storage before TTL |