Chapter 12 · Time Series and Geospatial Workloads

Aggregations, Downsampling, Compaction Rules, and Multi-Series Queries

Turn raw AtlasMart telemetry into bounded time buckets and derived series while keeping bucket alignment, compaction state, labels, and multi-series aggregation observable.

Intermediate180–220 minutesAggregation and compactionRedis Open Source 8.10.1Free/local-firstLast reviewed: September 6, 2026

Learning outcomes

AtlasMart’s raw temperature streams are useful for incident investigation, but dashboards and capacity planning need one-minute summaries across many sensors. The challenge is to reduce data volume without erasing bucket semantics or turning derived data into fake source truth.

01

Explain bucket duration, alignment, reported bucket timestamp, and partial latest-bucket semantics.

02

Run TS.RANGE aggregation separately from persisted compaction rules.

03

Create source→destination compaction rules and prove when a bucket becomes materialized.

04

Query many series with label filters and GROUPBY/REDUCE while bounding reply size.

05

Treat derived series as rebuildable state and measure memory/query cost before scaling.

Exact lab baseline

All Chapter 12 mandatory labs reuse the disposable Chapter 01 environment: Redis Open Source 8.10.1 from Docker Official Image redis:8.10.1, container atlasmart-redis-ch01, standalone topology, host publication 127.0.0.1:6379, TLS disabled only because traffic stays on loopback, default ACL user disabled, named users atlasmart-app and academy-admin, logical database 0, AOF with appendfsync everysec plus RDB snapshots, persistent /data, and no explicit maxmemory limit or eviction policy. Redis 8 integrates Time Series into Redis Open Source; geospatial commands are core Redis commands. Fixtures stay under atlasmart:ch12:*. Mandatory work is local and uses synthetic telemetry/coordinates only; no paid service, production endpoint, or real credential is required.

1. Aggregation answers a different question than raw range reads

A raw sample says “sensor s01 reported 4.2 at timestamp t.” A bucket aggregate says “for this defined interval, the selected reducer produced a summary.” Those statements have different lineage. avg, max, sum, count, and time-weighted average (twa) are reducers, not storage formats.

Layer Question Authoritative for
Raw series What samples were ingested? Ingested measurement history within retention
On-demand TS.RANGE aggregation What is the aggregate for this query definition? The query result at that time
Compaction destination What derived buckets were materialized by the rule? Rebuildable summary state
Application aggregate What business metric combines Redis and non-Redis context? The application-defined result

2. Build deterministic raw series with bounded labels

redis-cli · source and destination setup
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.CREATE atlasmart:ch12:raw:temp:baku-01:s01 RETENTION 3600000 DUPLICATE_POLICY BLOCK LABELS tenant atlasmart site baku-01 zone cold-a metric temperature sensor s01 unit Cdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.CREATE atlasmart:ch12:raw:temp:baku-01:s02 RETENTION 3600000 DUPLICATE_POLICY BLOCK LABELS tenant atlasmart site baku-01 zone cold-a metric temperature sensor s02 unit Cdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.MADD atlasmart:ch12:raw:temp:baku-01:s01 0 4 atlasmart:ch12:raw:temp:baku-01:s01 20000 6 atlasmart:ch12:raw:temp:baku-01:s01 40000 8 atlasmart:ch12:raw:temp:baku-01:s01 60000 10 atlasmart:ch12:raw:temp:baku-01:s01 80000 12 atlasmart:ch12:raw:temp:baku-01:s02 0 5 atlasmart:ch12:raw:temp:baku-01:s02 20000 7 atlasmart:ch12:raw:temp:baku-01:s02 40000 9 atlasmart:ch12:raw:temp:baku-01:s02 60000 11 atlasmart:ch12:raw:temp:baku-01:s02 80000 13docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.INFO atlasmart:ch12:raw:temp:baku-01:s01

Using timestamps that fall exactly around 60,000-ms boundaries makes bucket behavior auditable by eye.

3. On-demand aggregation: bucket duration and alignment are part of the result

With no ALIGN, bucket boundaries are aligned to multiples of the bucket duration from reference timestamp zero. Changing alignment changes which raw samples share a bucket even when the source data is identical.

redis-cli · compare raw and aggregated ranges
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 120000docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 120000 AGGREGATION avg 60000docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 10000 120000 ALIGN 10000 AGGREGATION avg 60000docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 120000 AGGREGATION min,avg,max 60000

Expected first aligned bucket for s01 at [0,60000) uses values 4, 6, and 8; the sample at 60000 belongs to the next bucket. The min,avg,max multi-aggregator syntax is available in current Redis Time Series; older client wrappers may lag even when the server supports it.

4. Bucket timestamps can report start, midpoint, or end

redis-cli · same bucket values, different reported timestamps
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 120000 AGGREGATION avg 60000 BUCKETTIMESTAMP startdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 120000 AGGREGATION avg 60000 BUCKETTIMESTAMP middocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 120000 AGGREGATION avg 60000 BUCKETTIMESTAMP end

A dashboard that labels bucket timestamps inconsistently can appear shifted even when the aggregate values are identical. Record the bucket timestamp convention as part of the metric contract.

5. Create a persistent compaction rule and observe bucket closure

A compaction rule writes a derived destination series as source buckets close. The destination must be treated as derived state with its own retention plan. Create the rule before inserting the demonstration samples so the lab never implies that rule creation backfills older source history.

redis-cli · materialized one-minute average with rule-first setup
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.CREATE atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 RETENTION 3600000 DUPLICATE_POLICY BLOCK LABELS tenant atlasmart site baku-01 zone cold-a metric temperature sensor s01-demo unit Cdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.CREATE atlasmart:ch12:rollup:rule-demo:temp:baku-01:s01:1m RETENTION 86400000 DUPLICATE_POLICY BLOCK LABELS tenant atlasmart site baku-01 zone cold-a metric temperature_1m source s01-demo unit C derived yesdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.CREATERULE atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 atlasmart:ch12:rollup:rule-demo:temp:baku-01:s01:1m AGGREGATION avg 60000 0docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.MADD atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 0 4 atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 20000 6 atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 40000 8 atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 60000 10 atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 80000 12docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.INFO atlasmart:ch12:raw:rule-demo:temp:baku-01:s01docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.INFO atlasmart:ch12:rollup:rule-demo:temp:baku-01:s01:1mdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:rollup:rule-demo:temp:baku-01:s01:1m - +
Rule timing matters

A compaction bucket is normally finalized when a later sample opens the next bucket. LATEST can expose the current partial compacted bucket in range queries. A partial bucket is not equivalent to a closed period and should be labeled accordingly in dashboards.

6. Wrong approach: assume compaction can replace raw truth immediately

Suppose AtlasMart keeps only one-minute averages, then an incident asks whether temperature briefly exceeded 8.5°C for five seconds. The average may hide the excursion. Downsampling is a loss of detail even when the reducer is exact for its bucket.

redis-cli · compare raw maximum with average rollup
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 59999docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 59999 AGGREGATION avg 60000docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.RANGE atlasmart:ch12:raw:temp:baku-01:s01 0 59999 AGGREGATION max 60000

The repair is a retention hierarchy: preserve raw samples for the investigation horizon, maintain appropriate derived aggregates for longer horizons, and document which questions each tier can answer. Do not select retention values by folklore; derive them from audit, incident, cost, and query requirements.

7. Multi-series queries select by labels, then aggregate samples

redis-cli · inspect selected series and their ranges
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.QUERYINDEX tenant=atlasmart site=baku-01 metric=temperaturedocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.MRANGE 0 120000 WITHLABELS COUNT 10 FILTER tenant=atlasmart site=baku-01 metric=temperaturedocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.MRANGE 0 120000 WITHLABELS AGGREGATION avg 60000 FILTER tenant=atlasmart site=baku-01 metric=temperature

FILTER first chooses matching series by labels; aggregation then operates on each selected series. COUNT bounds samples/buckets per series, but total reply size still grows with the number of matching series.

8. GROUPBY/REDUCE performs cross-series aggregation after per-series work

redis-cli · combine sensors by a bounded label
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.MRANGE 0 120000 WITHLABELS AGGREGATION avg 60000 FILTER tenant=atlasmart site=baku-01 metric=temperature GROUPBY zone REDUCE avgdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.MRANGE 0 120000 WITHLABELS FILTER tenant=atlasmart site=baku-01 metric=temperature GROUPBY zone REDUCE max

GROUPBY zone REDUCE avg is appropriate only if zone has a controlled vocabulary and averaging sensor outputs is meaningful. A reducer can be mathematically valid but semantically wrong—for example averaging counters that should be summed.

9. Redis 8.10 adds new Time Series query/read surfaces

Redis 8.10 adds TS.NRANGE/TS.NREVRANGE (results grouped by timestamp), TS.READ (optionally blocking reads), TS.QUERYLABELS, and EXCLUDEEMPTY for multi-range queries. These are useful current capabilities, but they are version-sensitive extensions rather than assumptions for clients targeting older Redis 8.x deployments.

redis-cli · prove feature availability before depending on it
docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin COMMAND INFO TS.NRANGE TS.NREVRANGE TS.READ TS.QUERYLABELS TS.MRANGE

Client-library wrappers may not immediately expose new server commands. Raw command execution is a learning fallback, not an excuse to skip client compatibility tests.

10. Memory, query width, and compaction fan-out are capacity dimensions

redis-cli · source/rollup memory and latency evidence
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app MEMORY USAGE atlasmart:ch12:raw:temp:baku-01:s01docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app MEMORY USAGE atlasmart:ch12:raw:temp:baku-01:s02docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app MEMORY USAGE atlasmart:ch12:rollup:rule-demo:temp:baku-01:s01:1mdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin INFO commandstatsdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin INFO latencystats

Measure memory per source series, memory per derived series, number of rules per source, query series matched, buckets returned, and tail latency under concurrent writes. One tiny lab cannot produce a universal safe series count.

11. Cleanup the rule before deleting its keys

redis-cli · bounded compaction cleanup
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app TS.DELETERULE atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 atlasmart:ch12:rollup:rule-demo:temp:baku-01:s01:1mdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin UNLINK atlasmart:ch12:raw:temp:baku-01:s01 atlasmart:ch12:raw:temp:baku-01:s02 atlasmart:ch12:raw:rule-demo:temp:baku-01:s01 atlasmart:ch12:rollup:rule-demo:temp:baku-01:s01:1m

Deleting the explicit rule first keeps the reset understandable. On a disposable fixture, deleting keys may also remove rule state, but the lab teaches the lifecycle you should reason about operationally.

12. Production judgment

Use server-side range aggregation when the reducer and bucket contract are stable and moving fewer samples over the network materially helps. Use compaction when derived summaries are repeatedly queried and their lineage/retention are explicit. Avoid high-cardinality labels, unbounded multi-series replies, and compaction rule explosions. In replication and persistence, every source and derived write adds downstream work. In Cluster or managed services, verify multi-series behavior, routing, quotas, and client support on the actual target topology. Preserve a rebuild path for derived series.

Check your understanding

  1. What changes when ALIGN changes?
  2. Why is a compaction destination not raw truth?
  3. What does COUNT bound in TS.MRANGE?
  4. Why can GROUPBY on a user ID be dangerous?
  5. What is the operational benefit of treating rollups as rebuildable?
Review the answers

Which raw samples belong to each bucket, and therefore potentially the aggregate values and reported timestamps.

It stores derived bucket summaries and intentionally loses sample-level detail.

Samples/buckets per selected series, not the number of matching series.

It can create effectively unbounded groups and high metadata/query cardinality.

You can change rules, recover corruption, migrate versions, or backfill without pretending derived state is irreplaceable.

13. Summary and next step

You can now distinguish raw range reads, on-demand aggregation, persistent compaction, cross-series selection, and cross-series reduction. Lesson 3 shifts from time to space and builds a location index with correct coordinate order, distance units, radius/box queries, and precision limits.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.