MongoDB TTL indexes: auto-expiring documents explained
TTL index creation, expireAfterSeconds, background cleanup thread, TTL index limitations, session storage use case, partial filter indexes
Automatic document expiry with TTL
A TTL (Time-To-Live) index automatically deletes documents once a configurable number of seconds has passed since a specified Date field. MongoDB's internal background thread scans TTL indexes every 60 seconds and removes all expired documents. This makes TTL indexes the cleanest solution for sessions, OTP tokens, password reset links, rate-limit counters, and any other time-bounded data.
// Documents expire 1 hour after their createdAt Date value
await db.collection('sessions').createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 3600 }
)
await db.collection('sessions').insertOne({
userId: 'u1',
token: 'eyJhbGci...',
createdAt: new Date() // MUST be a BSON Date, not a string
})
// Expire at a specific future timestamp instead of a duration
await db.collection('flash_sales').createIndex(
{ expireAt: 1 },
{ expireAfterSeconds: 0 } // expire at the exact Date stored in expireAt
)
await db.collection('flash_sales').insertOne({
name: 'Black Friday',
expireAt: new Date('2024-12-01T23:59:59Z')
})Important limitations
TTL indexes only apply to fields of BSON Date type or arrays of Dates. They cannot be compound indexes. Deletion timing is approximate โ the background thread runs every 60 seconds, so a document may persist up to 60 seconds past its expiry time. Always add application-level expiry checks for any security-sensitive validation such as session tokens or one-time codes.
