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.

Wheredocument type
Valueinteger, seconds, 3600 (one hour) to 31536000 (one year)
Defaultabsent: documents live until someone deletes them
Sinceprotocol version 14
On updateFixed (DocumentTypeUpdateError, 40212): an update may not add, remove or change it
ErrorsDocumentExpiredError (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 $createdAt plus ttl seconds. $createdAt is 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 where canBeDeleted allows.
  • Earlier deletion. The owner may delete a document before it expires when canBeDeleted allows it, and the contract's moderators when moderatorAbilities.delete does. canBeDeleted: false only 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.

  • $createdAt must be in required.
  • Refused together with documentsKeepHistory: true (Drive never deletes a document whose type keeps history), with indexOnly: 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_seconds and at most max_document_ttl_seconds of SystemLimits: 3600 and 31536000 at protocol version 14. The meta-schema itself admits 1 to 4294967295, so a ttl of 0 is a JsonSchemaError (10101) and one outside the narrower bounds is 10231.
  • For references, a type with a ttl is deletable. A permanentDocument reference and a listElement reference may not point at it, a lookup included (ReferencedDocumentTypeDeletableError, 40122); a deletableDocument reference 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