Time To Live (ttl)
ttl gives every document of a type a lifetime. The platform deletes each document once that many seconds have passed since it was created, whoever owns it and whatever the type says about who else may delete it. Use it for content that is meant to disappear: stories, invitations, offers, session records. Such documents are also cheaper: they pay for the time they occupy the state rather than for storage forever.
This is the document type keyword. An index can carry a ttl of its own inside timeRange, which expires index entries and leaves the documents in place; see Time-Range Indexes.
| Where | document type |
| Value | integer, seconds, 3600 (one hour) to 31536000 (one year) |
| Default | absent: documents live until someone deletes them |
| Since | protocol version 14 |
| On update | Fixed (DocumentTypeUpdateError, 40212): an update may not add, remove or change it |
| Errors | DocumentExpiredError (40140) for a replace, transfer, purchase or price update of a document past its expiry |
Example
"story": {
"type": "object",
"ttl": 86400,
"canBeDeleted": true,
"properties": {
"caption": { "type": "string", "maxLength": 200, "position": 0 },
"mediaUrl": { "type": "string", "maxLength": 500, "position": 1 }
},
"required": ["$createdAt", "mediaUrl"],
"additionalProperties": false
}
Each story is deleted one day (86,400 seconds) after its creation. Its author may delete it sooner. $createdAt must be in required, since the expiry is counted from it.
How it works
- When a document expires. At its
$createdAtplusttlseconds.$createdAtis the block time of the create, so nothing the writer sends moves the expiry, and documents created in the same block expire together. A replace, transfer, purchase or price update never moves it either: a buyer of an expiring document buys what is left of its life. - When it is deleted. After each block's state transitions, the platform deletes expired documents, oldest first: at most 128 per block, and at most 1,024 in weight, where a document weighs 1 plus the index levels of its type (the values at protocol version 14). The rest wait for the next block. The deletion is an ordinary one: the document and every index entry go, and counts and sums are brought down.
- Between expiry and deletion. A document past its expiry that the cleanup has not reached yet can still be queried and referenced, and it still holds its values in the type's unique indexes, so a create with the same unique value is refused as a duplicate until the cleanup has run. It can no longer be replaced, transferred, bought or repriced, and a moderator can no longer restore it: each is refused, paid, with
DocumentExpiredError(40140). Its owner may still delete it wherecanBeDeletedallows. - Earlier deletion. The owner may delete a document before it expires when
canBeDeletedallows it, and the contract's moderators whenmoderatorAbilities.deletedoes.canBeDeleted: falseonly stops the owner; the platform still deletes the document when it expires. - What it costs. The document is stored without storage flags and refunds nothing when it is deleted, by anyone. Instead of the price of permanent storage, each byte it writes pays a price for the time it will live: five tiers up to seven days, then a price per 9.125 days spanned. Creating it also prepays, as processing, the cost of its later deletion. A replace, transfer, purchase or price update pays for the bytes it adds at the price of the lifetime left. See Fees.
- Proofs near the expiry. A write accepted in the last block before a document expires proves the document present. A proof fetched after the next block's cleanup finds it gone. The one-hour minimum keeps a newly created document in the state well past the moment its writer fetches the proof of the create.
Rules at registration
The refusals below are InvalidContractStructure (10231) unless a bullet says otherwise. They hold on every parse of the contract, except the bounds, which are checked when a contract is registered or updated.
$createdAtmust be inrequired.- Refused together with
documentsKeepHistory: true(Drive never deletes a document whose type keeps history), withindexOnly: true(there is no stored row to delete by id), and on a type with a contested index (a contested document waits in its vote poll, and could expire before it is stored). - At least
min_document_ttl_secondsand at mostmax_document_ttl_secondsofSystemLimits: 3600 and 31536000 at protocol version 14. The meta-schema itself admits 1 to 4294967295, so attlof 0 is aJsonSchemaError(10101) and one outside the narrower bounds is 10231. - For references, a type with a
ttlis deletable. ApermanentDocumentreference and alistElementreference may not point at it, a lookup included (ReferencedDocumentTypeDeletableError, 40122); adeletableDocumentreference may. See References.
Everything else combines with a ttl: mutable types, transferable, tradeMode, moderatorAbilities.delete, creationRestrictionMode, count, sum and ranked indexes, timeRange indexes with or without their own ttl, references declared on the type, action fees and token costs.
On update
An update may not add, remove or change the ttl of an existing document type. Every stored document has the expiry it was written and paid with: adding one would leave stored documents that the cleanup cannot find, removing it would leave entries that delete documents the type says live forever, and changing it would move expiries away from what was paid for. A document type added by an update may declare a ttl freely.
See also
- Document Time To Live, for the expirations tree, the fee tiers, the payout to epochs and the cleanup
- Deletion, for the other two ways a document is deleted
- Time-Range Indexes, for the index
ttl - History, for why a type that keeps history cannot expire
- System Properties, for
$createdAt