This document provides an introduction to MongoDB's "time to live" or collection feature. TTL collections make it possible to store data in MongoDB and have the automatically remove data after a specified number of seconds or at a specific clock time.
Data expiration is useful for some classes of information, including machine generated event data, logs, and session information that only need to persist for a limited period of time.
A special TTL index property supports the implementation of TTL collections. The TTL feature relies on a background thread in that reads the date-typed values in the index and removes expired from the collection.
Procedures
To create a , use the method with the expireAfterSeconds option on a field whose value is either a or an array that contains
Note
The TTL index is a single field index. Compound indexes do not support the TTL property. For more information on TTL indexes, see TTL Indexes.
You can modify the expireAfterSeconds of an existing TTL index using the command.
Expire Documents after a Specified Number of Seconds
To expire data after a specified number of seconds has passed since the indexed field, create a TTL index on a field that holds values of BSON date type or an array of BSON date-typed objects and specify a positive non-zero value in the expireAfterSeconds field. A document will expire when the number of seconds in the expireAfterSeconds field has passed since the time specified in its indexed field.
For example, the following operation creates an index on the
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 10 } ) |
When adding documents to the
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
MongoDB will automatically delete documents from the
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
Expire Documents at a Specific Clock Time
To expire documents at a specific clock time, begin by creating a TTL index on a field that holds values of BSON date type or an array of BSON date-typed objects and specify an expireAfterSeconds value of
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
For example, the following operation creates an index on the
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
For each document, set the value of
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
db.log_events.insertOne( { |
"expireAt": new Date('July 22, 2013 14:00:00'), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.insertOne( { |
"expireAt": new Date('July 22, 2013 14:00:00'), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
MongoDB will automatically delete documents from the
db.log_events.insertOne( { |
"createdAt": new Date(), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
Indexes Configured Using NaN
Warning
Possible Data Loss
When a TTL index has expireAfterSeconds set to
db.log_events.insertOne( { |
"expireAt": new Date('July 22, 2013 14:00:00'), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
Do not set expireAfterSeconds to
db.log_events.insertOne( { |
"expireAt": new Date('July 22, 2013 14:00:00'), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
Prior to MongoDB 5.0, when a TTL index has expireAfterSeconds set to
db.log_events.insertOne( { |
"expireAt": new Date('July 22, 2013 14:00:00'), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
From MongoDB 5.0.0 - 5.0.13 (and 6.0.0 - 6.0.1),
db.log_events.insertOne( { |
"expireAt": new Date('July 22, 2013 14:00:00'), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } ) |
db.log_events.insertOne( { |
"expireAt": new Date('July 22, 2013 14:00:00'), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
Starting in MongoDB 5.0.14 (and 6.0.2), the server will not use TTL indexes that have expireAfterSeconds set to
db.log_events.insertOne( { |
"expireAt": new Date('July 22, 2013 14:00:00'), |
"logEvent": 2, |
"logMessage": "Success!" |
} ) |
However, there are still some situations which may result in unexpected behavior. Documents may expire:
During an initial sync to an earlier version from MongoDB 5.0.0 - 5.0.13 (or 6.0.0 - 6.0.1).
When upgrading from an earlier version to MongoDB 5.0.0 - 5.0.13.
When restoring a collection from a pre-5.0
into a MongoDB 5.0.0 - 5.0.13 (or 6.0.0 - 6.0.1) instance.
To avoid problems, either drop or correct any misconfigured TTL indexes.
1
Run the following script in the shell. The script does not work in the legacy mongod2 shell.Identify misconfigured indexes.
function getNaNIndexes() { const nan_index = []; const dbs = db.adminCommand({ listDatabases: 1 }).databases; dbs.forEach((d) => { const listCollCursor = db .getSiblingDB(d.name) .runCommand({ listCollections: 1 }).cursor; const collDetails = { db: listCollCursor.ns.split(".$cmd")[0], colls: listCollCursor.firstBatch.map((c) => c.name), }; collDetails.colls.forEach((c) => db .getSiblingDB(collDetails.db) .getCollection(c) .getIndexes() .forEach((entry) => { if (Object.is(entry.expireAfterSeconds, NaN)) { nan_index.push({ ns: `${collDetails.db}.${c}`, index: entry }); } }) ); }); return nan_index; }; getNaNIndexes();
2
Use the command to update any misconfigured expireAfterSeconds values that the script found. As an alternative, you can any misconfigured TTL indexes and recreate them later using the command.Correct misconfigured indexes.