Using MongoDB TTL Indexes to Auto‑Expire Session Tokens
See how MongoDB TTL indexes automatically delete expired session tokens, with a step‑by‑step example and notes on latency and maintenance.
18 Jun 2026, 00:21 UTC

Problem: cleaning up temporary data without extra code
Applications often create data that is only needed for a short period—authentication tokens, debug logs, or temporary cache entries. If this data is left in the database it wastes storage and can cause security or compliance issues. Writing a separate cleanup job adds operational overhead and introduces failure points.
Thesis: TTL indexes let MongoDB remove expired documents automatically
A TTL (Time‑To‑Live) index is a special index on a BSON Date field. MongoDB runs a background thread roughly every 60 seconds, scans the index, and deletes any document whose date value is older than the expireAfterSeconds value you set when creating the index. No application‑side scheduler is required.
How to create a TTL index
You need readWrite access on the target database. The index is created with the createIndex command, specifying the date field and the expireAfterSeconds option.
use myapp
db.sessions.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 1800 }
)
The field createdAt must contain a BSON Date (or an array of Dates). The value 1800 means “remove the document 1800 seconds after the time stored in createdAt”.
Worked example: session store
Imagine a sessions collection that holds authentication sessions. Each session document includes a createdAt timestamp set when the session is issued. We want sessions to disappear after 30 minutes.
use myapp
// Insert a sample session
db.sessions.insertOne({
userId: "alice",
token: "9f8c4e2a-1b3d-4f6a-9c7e-2d5b6a7c8d9e",
createdAt: new Date()
})
// Create TTL index: expire 30 minutes after createdAt
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 1800 })
To confirm the index exists:
db.sessions.getIndexes()
// Look for the entry that contains "expireAfterSeconds" : 1800
After waiting longer than 30 minutes (plus up to one minute for the background thread), a simple query should show the document gone:
db.sessions.countDocuments({ token: "9f8c4e2a-1b3d-4f6a-9c7e-2d5b6a7c8d9e" })
// Expected result: 0
Trade‑offs and limitations
- Deletion latency: The background thread runs approximately every 60 seconds, so a document may remain in the collection for up to that interval after its expiry time.
- Impact on write load: If many documents expire at the same second, the deletion burst can increase disk I/O and temporarily affect write throughput.
- Capped collections: TTL indexes cannot be created on capped collections.
- Changing expiration: To modify
expireAfterSecondsyou must drop the existing index (db.collection.dropIndex("field_1")) and recreate it with the new value.
Practical verification and best practices
- Test with a short expiry (e.g., 10 seconds) and confirm removal after the interval plus up to 60 seconds.
- Monitor the TTL thread via
db.currentOp(); look for "ttl" in the operation description. - Spread expiry times (add a small random jitter to the date field) to avoid thundering‑herd deletion spikes.
- Store all date values in UTC to prevent timezone‑related surprises.
Closing
TTL indexes give you a low‑maintenance way to let MongoDB handle automatic removal of temporary data. By accounting for the up‑to‑60‑second deletion lag, understanding the write‑impact of bulk expirations, and knowing that expiration changes require index recreation, you can safely apply this feature to session stores, log rolling, or short‑term caches.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.