MongoDB time-series.
Create
db.createCollection("metrics", {
timeseries: {
timeField: "ts",
metaField: "sensor",
granularity: "minutes", // seconds, minutes, hours
},
expireAfterSeconds: 86400 * 30,
})
metaField: tags / dimensions (sensor id, region).
Insert
db.metrics.insertMany([
{ ts: ISODate(), sensor: { id: 1, region: "ny" }, temp: 22.5 },
{ ts: ISODate(), sensor: { id: 1, region: "ny" }, temp: 22.6 },
])
Query
db.metrics.find({
"sensor.id": 1,
ts: { $gte: ISODate("2026-01-15"), $lte: ISODate("2026-01-16") },
})
Aggregation: bucket
db.metrics.aggregate([
{ $match: { "sensor.id": 1, ts: { $gte: ..., $lte: ... } } },
{
$group: {
_id: {
$dateTrunc: { date: "$ts", unit: "hour" },
},
avg: { $avg: "$temp" },
min: { $min: "$temp" },
max: { $max: "$temp" },
},
},
{ $sort: { _id: 1 } },
])
Granularity choice
seconds: high-frequency (>1/min).minutes: typical (1-60/min).hours: low-frequency (<1/min).
Mongo internally buckets writes for compression.
Compression
Time-series collections compress similar data efficiently. 5-10x vs regular.
Indexes
db.metrics.createIndex({ "sensor.id": 1, ts: 1 })
Auto-creates index on ts + metaField.
Retention (TTL)
expireAfterSeconds: 86400 * 30 // 30 days
Auto-deletes old buckets.
Window functions
db.metrics.aggregate([
{ $match: { ... } },
{
$setWindowFields: {
partitionBy: "$sensor.id",
sortBy: { ts: 1 },
output: {
rolling_avg: {
$avg: "$temp",
window: { range: [-1, 0], unit: "hour" },
},
},
},
},
])
Rolling averages, cumulative sums.
Downsampling
Manually aggregate to lower-resolution collection:
db.metrics.aggregate([
{ $group: { _id: { sensor: "$sensor", hour: { $dateTrunc: { date: "$ts", unit: "hour" } } }, avg: { $avg: "$temp" } } },
{ $merge: "metrics_hourly" },
])
Schedule daily.
Compared to Prometheus / Influx
Mongo time-series: good if Mongo already in stack. For pure metrics + huge scale: Prometheus or VictoriaMetrics + Grafana.
Common mistakes
- Wrong granularity → poor compression.
- Updates / deletes (limited in TS collections).
- No retention → infinite growth.
- Querying without
metaField→ scatter. - Wrong index choice.
Read this next
If you want my Mongo TS setup, it’s at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .