# Advanced — Time Series **Capability:** `MongoCapability.TIME_SERIES` **Property:** `ca-skeleton.persistence-mongo.advanced.time-series.enabled` **Status:** Advanced. ## Requirements | | | |---|---| | Topology | Replica set or sharded cluster. | | Server | MongoDB 7.0 or 8.0. | | Privilege | Standard application role; collection creation goes through the admin plane. | ## Descriptor `MongoTimeSeriesDescriptor` declares: - **timeField** — required, a BSON date. This is the bucketing axis. - **metaField** — optional but nearly always wanted: the series identity (device id, tenant, sensor). Documents sharing a `metaField` value bucket together, which is where the compression comes from. - **granularity** — `MongoTimeSeriesGranularity`: | Granularity | Bucket span | Use for | |---|---|---| | `SECONDS` | 1 hour | Sub-second to per-second ingest. | | `MINUTES` | 24 hours | Per-minute metrics. | | `HOURS` | 30 days | Hourly rollups. | Granularity that is too fine produces many small buckets and loses the compression; too coarse produces oversized buckets that must be read whole to answer a narrow query. ## What a time series collection is not `MongoTimeSeriesCapabilityValidator` refuses the operations the collection type does not support, at declaration time rather than at first use: - **No arbitrary updates.** Time series data is append-mostly. Delete and limited update support exists on recent servers but is not part of this platform's contract. - **No unique index on the measurement.** There is no `_id` to be unique on in the usual sense. - **No CSFLE.** Refused — see [encryption.md](encryption.md). - **No change stream on the raw buckets** as a business event source. The bucket documents are a storage representation, not your measurements. Converting an existing regular collection to a time series collection is a copy, not an alter. Plan it as a migration with a dual-write window. ## TTL Time series collections use `expireAfterSeconds` on the collection rather than a TTL index on a field. The [TTL rules](../schema-index-migration-guide.md#4-ttl) still apply: expiry is physical cleanup on a bucket boundary, so a measurement can outlive its expiry by up to a bucket span plus the monitor interval. Do not treat absence as a deadline. ## Operations `MongoTimeSeriesOperations` is the port for insert and windowed read. Reads are bounded by the same `MongoOperationBudget` as everything else: an unbounded time-range query on a time series collection is the fastest way to read a year of data into heap. ## Failure recovery | Symptom | Cause | Action | |---|---|---| | Writes rejected with an unsupported-operation error | An update or unique-index expectation | The collection type does not support it; change the access pattern. | | Poor compression / large storage | Missing `metaField`, or granularity too fine | Both require a rebuild; measure on a copy before committing. | | Slow range queries | Granularity too coarse for the query window | Same: rebuild with the granularity matched to the dominant query. | ## Promotion evidence Actual-topology evidence on the target deployment, a migration path from the existing collection, failure cases (unsupported update refused, CSFLE combination refused), and this document as the runbook.