mongodb/mongo
Time-series collections
A time-series collection is a collection optimized for telemetry-style workloads: many small documents tagged with a timestamp and a small set of dimensions. Internally each time-series collection is two things: a user-facing view and an underlying bucket collection that packs many measurements into a single bucket document. The implementation lives at src/mongo/db/timeseries/, with query rewrites in src/mongo/db/exec/timeseries/ and src/mongo/db/query/timeseries/.
Purpose
Time-series collections provide:
- Storage savings — bucket compression dramatically reduces on-disk size for telemetry workloads (often >10x).
- Faster scans — a single bucket holds many measurements, so a full scan touches far fewer documents.
- Native operators —
$_internalUnpackBucket,$densify,$fill,$setWindowFieldsintegrate cleanly with the columnar bucket format. - Familiar API — users insert ordinary documents; the server transparently routes them into buckets.
Bucketing
When a measurement arrives, the server picks (or creates) a bucket based on:
- The time-series options (
timeField,metaField,granularityorbucketMaxSpanSeconds). - The current open buckets cached in the bucket catalog (
src/mongo/db/timeseries/bucket_catalog/).
graph TD
Insert[insert measurement] --> Catalog[BucketCatalog]
Catalog -->|find or open| Bucket[Bucket document]
Bucket -->|append measurement| Storage[bucket collection<br/>system.buckets.foo]A bucket is a document in system.buckets.<coll> with three fields:
control— min/max metadata, version, count.meta— the per-bucket metadata value (the dimensional tag the user specified).data— a bsoncolumn column store of measurements, one column per field name.
bsoncolumn
The data field uses the bsoncolumn format defined in src/mongo/bson/column/. It's a difference-encoded, run-length-compressed binary format that fits a column of timestamped floats or strings into a fraction of the bytes a sequence of standalone BSON documents would take. The codec is documented in src/mongo/bson/column/.
Reading: the unpack stage
Queries against a time-series collection see the user-facing view, but the actual scan reads buckets. The pipeline rewriter inserts an $_internalUnpackBucket stage that:
- Reads bucket documents from
system.buckets.<coll>. - Decodes the columnar data.
- Emits one synthetic measurement document per measurement.
graph LR
BucketColl[system.buckets.foo] --> Scan[FETCH/IXSCAN]
Scan --> Unpack[$_internalUnpackBucket]
Unpack --> Match[$match / user pipeline]The unpack stage is predicate-aware — many $match filters can be evaluated against the bucket-level control.min/control.max and skip the bucket entirely without decoding it. This makes time-range queries dramatically faster than scanning every measurement.
Compression and reopen
When a bucket fills (size or count threshold), it is closed and a new bucket opens for that meta value. Closed buckets are compressed: the columnar format described above plus an additional encoding pass. The server can also reopen a closed bucket if late-arriving data needs to be inserted into it.
Sharding
Time-series collections can be sharded. The shard key may include a time field (commonly bucketed by hour or day) and the meta field. The router targets shards based on bucket boundaries; the data side translates each measurement into the bucket it belongs in. See Sharding and src/mongo/s/commands/cluster_* for the router-side support.
Updates and deletes
Time-series collections support update and delete with a feature-flagged code path that:
- Identifies the buckets touched.
- Either modifies measurements within the bucket in place (when the bucket is open) or rewrites the bucket (when it's closed).
- Replicates an
applyOpscontaining the bucket-level update.
Key source files
| File | Purpose |
|---|---|
src/mongo/db/timeseries/bucket_catalog/ |
The in-memory cache of open buckets. |
src/mongo/db/timeseries/bucket_compression.cpp |
Bucket compression and reopen logic. |
src/mongo/db/timeseries/timeseries_options.cpp |
Per-collection options (timeField, metaField, granularity). |
src/mongo/db/timeseries/write_ops/ |
Inserts, updates, deletes on time-series collections. |
src/mongo/db/exec/timeseries/ |
Bucket-aware execution stages. |
src/mongo/db/query/timeseries/ |
Query-planner support for unpacking buckets. |
src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp |
The $_internalUnpackBucket stage. |
src/mongo/bson/column/ |
The bsoncolumn columnar format. |
Integration points
- The storage engine stores the bucket collection like any other collection — buckets are just BSON documents.
- Aggregation pipeline rewrites pipelines to insert the unpack stage and push predicates down to bucket-level metadata.
- Query engine indexes can be built on the bucket fields (timestamp, meta, computed columns).
- Sharding supports sharded time-series collections.
- Change streams translate bucket-level oplog entries back into measurement-level events.
Entry points for modification
Most time-series work touches the bucket catalog or the unpack stage. New columnar codecs go in src/mongo/bson/column/. New time-series-aware optimizations are usually pipeline rewrites under src/mongo/db/pipeline/. The core and aggregation resmoke suites have time-series subdirectories that pin behavior; the FSM workloads under jstests/concurrency/ exercise the bucket catalog under contention.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.