Chapter 21 · TTL, Retention, Expiration, Backfills, and Lifecycle Automation
Index Exemptions for TTL Fields, Sequential Timestamp Costs, and Write Throughput Considerations
Design TTL fields and indexes so retention does not create avoidable write hotspots or index fan-out, and verify the Standard-versus-Enterprise indexing boundary before production rollout.
1. AtlasMart problem: the retention field becomes the write bottleneck
AtlasMart writes large numbers of short-lived telemetry events.
Every event gets a timestamp-like expireAt that
increases with creation time. In Standard edition, automatic
single-field indexing means this monotonic field can concentrate
index writes in a narrow range. The documented limit for a
collection with an indexed sequential field is 500 writes per
second. TTL itself needs the field value; your application
usually does not need that field indexed for queries.
Keeping the automatic index can therefore impose a throughput
constraint that the retention policy did not require.
- Explain why sequential indexed timestamps create a Standard-edition hotspot risk.
- Combine TTL and a single-field index exemption on the same field configuration.
- Distinguish Standard automatic indexing from Enterprise optional indexing.
- Estimate index/write amplification before and after exemptions rather than disabling indexes blindly.
- Preserve query requirements by inventorying every access pattern that genuinely needs the TTL field indexed.
Use the Emulator Suite, a Firebase demo project, or an isolated test project for destructive, security-sensitive, billing-sensitive, migration, backup/restore, or write-heavy exercises unless the lesson explicitly marks managed verification as required. Treat shown output as expected evidence unless it is explicitly identified as captured output, and re-check current Firebase/Google Cloud edition, mode, quota, pricing, and security documentation before production execution.
AtlasMart keeps the course-wide project identity
demo-atlasmart-firestore. Mandatory work is local
and no-cost: Node.js 22+, Firebase CLI 15.30.0,
Firestore emulator 127.0.0.1:8080, Auth emulator
127.0.0.1:9099, Emulator UI
127.0.0.1:4000, and the same Standard-edition
Native-mode mental model used by earlier chapters. The default
database is (default). TTL sweeping itself is
not treated as an emulator guarantee: the lab
models eligibility and lifecycle rules deterministically,
while an optional real-project check verifies actual managed
TTL deletion only in an isolated billed project. TTL deletes
are excluded from Firestore's free usage and require billing.
Expiration is a business fact; TTL deletion is an
asynchronous storage-cleanup mechanism.
A document whose expireAt is in the past may
still exist and be returned by queries until the managed
sweeper deletes it. Therefore product behavior must filter or
reject expired state explicitly when timeliness matters. TTL
is not a scheduler, not a transaction boundary, not a
legal-hold engine, and not a substitute for backups/PITR.
2. TTL does not need a query index to delete documents
In Standard Native mode, the TTL field may be indexed or unindexed. Firestore's TTL subsystem can use the policy even when you exempt the field from single-field query indexing. That means two independent decisions live on one field: “is this a TTL field?” and “should user queries get automatic indexes on it?” A single field-level configuration can hold both TTL and index-exemption settings.
| Question | If yes | If no |
|---|---|---|
Do application queries filter/order by
expireAt?
|
Retain the necessary query index and measure hotspot impact | Prefer an index exemption in Standard |
| Is the field monotonic across high-rate writes? | Treat as a hotspot candidate and load-test tail latency | Still measure; no assumption that indexing is free |
| Is this Enterprise optional-index mode? | Create an index only when Query Explain/query contracts justify it | An unindexed query may scan; that can work but be expensive |
| Does TTL need the query index? | No; TTL policy/index is separate from query-performance indexing | Keep policy while removing unnecessary query index |
3. Standard configuration: TTL + no automatic query index
{ "indexes": [], "fieldOverrides": [ { "collectionGroup": "events", "fieldPath": "expireAt", "ttl": true, "indexes": [] } ]}
This expresses two things together:
events.expireAt is the TTL policy field, and
automatic single-field indexing for that field is disabled.
Before deployment, verify that no query contract depends on
where("expireAt", ...) or
orderBy("expireAt"). If such a query exists,
redesign it or retain the needed index deliberately.
4. Why “disable all indexes” is the wrong repair
Chapter 15 already established that index fan-out affects writes. The correct response is not to delete indexes indiscriminately. In Standard edition every supported query must be backed by an index; removing an index that a production access pattern uses converts a write optimization into a read outage. Keep a versioned query inventory and tie every exemption to evidence.
| Field | Access pattern | Index decision | Reason |
|---|---|---|---|
tenantId |
tenant event feed | keep | Security/query selectivity requirement |
eventType |
filtered diagnostics | keep if query exists | User-visible access pattern |
expireAt |
retention only | exempt | TTL can operate without query index; monotonic hotspot risk |
payload |
never queried | exempt if large | Avoid storage/fan-out cost |
5. Mandatory local lab: compare schema/index intent, not fake throughput
The Firestore emulator is useful for validating writes, queries, and configuration parsing, but it is not evidence for production key-range/index hotspot physics. The lab therefore measures application-level operation counts and checks query contracts; it labels all latency numbers as local-only.
const queryContracts = [ { name:"tenant-feed", fields:["tenantId","createdAt"], required:true }, { name:"retention-sweeper", fields:["expireAt"], required:false, reason:"managed TTL" }];const exemptions = new Set(["events.expireAt","events.payload"]);for (const q of queryContracts) { if (q.required && q.fields.some(f => exemptions.has(`events.${f}`))) { throw new Error(`Unsafe exemption breaks ${q.name}`); }}console.log("index-contract: PASS");
Expected result: the index contract passes
because no user query relies on expireAt. Then seed
the same number of local events with and without your
application-side payload fields and capture operation counts. Do
not present emulator p95/p99 as Firestore production throughput.
6. Standard vs Enterprise interpretation
Standard automatically creates single-field indexes and enforces index-backed Core queries, so exemptions are an explicit performance tool. Enterprise Native uses optional indexing; an unindexed query can run as a scan, which changes the failure mode from “missing index” to “possibly large scan/read-unit cost.” MongoDB compatibility TTL indexes also do not double as query-planning indexes. The design question is therefore always: which index exists for retention, which for query execution, and what billing/performance model applies to this edition and operation family?
7. Controlled failure: benchmark only averages
A write path that averages 12 ms can still have unacceptable p95/p99 latency or contention errors during bursts. Production validation must report distribution and error classes, not only mean latency. Ramp safely in an isolated environment, record document IDs/key distribution/index configuration, and stop at budget/operation caps. Chapter 15's 500/50/5 guidance remains a ramp heuristic for new Standard collections—not a universal TTL limit.
Production judgment
Exempt a TTL timestamp when it is sequential, high-write, and not queried. Keep an index if product/query/security requirements genuinely need it, then test the consequences. In Enterprise, do not interpret “query runs without index” as proof that the scan is acceptable; use Query Explain and unit/latency evidence.
Verification checklist and cleanup
- Every index exemption maps to a documented query inventory.
- TTL configuration remains enabled after removing the query index.
- No local latency is mislabeled as production throughput.
- Standard/Enterprise index semantics are explicitly separated.
-
Rollback is the exact previous
firestore.indexes.jsonplus redeployment and query verification.
Bridge to Lesson 3
Indexing answers how to store expirable data efficiently. Lesson 3 asks a more fundamental question: should the data be soft-deleted, asynchronously TTL-deleted, batch-cleaned, or archived at all?
Knowledge check
- Does TTL require the field to remain query-indexed in Standard?
-
Why is an indexed
expireAtrisky at high write rates? - Why not disable all indexes?
- What changes in Enterprise optional-index mode?
- Can emulator p99 prove production hotspot behavior?
Review the answers
1. No. You can enable TTL and exempt the same field from automatic single-field query indexing.
2. It is usually monotonic; Standard documents a 500 writes/s collection limit when a sequential field is indexed.
3. Standard queries need indexes. Exempt only fields that no required query uses.
4. Queries can scan without an index, so success does not prove efficiency; use Query Explain and billing/latency evidence.
5. No. It can test application logic/configuration, not production split/index scheduling and capacity.
Summary and next step
This lesson established the working contract for Index Exemptions for TTL Fields, Sequential Timestamp Costs, and Write Throughput Considerations. Keep its edition/mode assumptions, trust boundary, verification evidence, and operational constraints explicit when reusing the pattern.
Next, continue to Soft Delete vs TTL vs Scheduled/Batch Cleanup vs Archive: Compliance and Product Requirements.
Authoritative references
- Firebase · Manage data retention with TTL policies
- Firebase · Firestore index overview and index exemptions
- Firebase · Cloud Firestore pricing and TTL billing
- Firebase · Firestore quotas and limits
- Firebase · Cloud Firestore triggers
- Firebase · Enterprise TTL indexes
- Google Cloud · MongoDB compatibility TTL indexes
- Google Cloud · MongoDB compatibility release notes
- Google Cloud · Firestore Monitoring metrics