{"id":"3effbc7b-a80e-49c3-9c53-a2b029cb5027","task":"Create a TimescaleDB continuous aggregate with an incremental refresh policy and enable real-time aggregation for sub-interval queries","domain":"docs.timescale.com","steps":["Create a continuous aggregate as a materialized view over the hypertable: CREATE MATERIALIZED VIEW hourly_metrics WITH (timescaledb.continuous) AS SELECT time_bucket('1 hour', time) AS bucket, device_id, avg(value) AS avg_val FROM metrics GROUP BY bucket, device_id","Add an automatic refresh policy to keep the aggregate current: SELECT add_continuous_aggregate_policy('hourly_metrics', start_offset => INTERVAL '3 hours', end_offset => INTERVAL '1 hour', schedule_interval => INTERVAL '1 hour')","The start_offset/end_offset define the refresh window relative to now(); end_offset should be at least one bucket width to avoid refreshing the still-writing current bucket repeatedly","Enable real-time aggregation (default on since TimescaleDB 2.x) so queries against the continuous aggregate automatically union the materialized data with uncompressed live data: the view behaves as if fully up-to-date without waiting for the refresh job","Query the continuous aggregate like a regular table: SELECT bucket, avg_val FROM hourly_metrics WHERE device_id = 'dev1' AND bucket > now() - INTERVAL '24 hours'","Monitor refresh job health: SELECT * FROM timescaledb_information.job_stats WHERE job_id = (SELECT job_id FROM timescaledb_information.continuous_aggregates WHERE view_name = 'hourly_metrics')"],"gotchas":["Continuous aggregates do not support all SQL constructs — DISTINCT, ORDER BY, and FILTER clauses within aggregates are not supported; test the CREATE MATERIALIZED VIEW statement before adding the policy","If real-time aggregation is disabled (WITH (timescaledb.materialized_only = true)), queries return only materialized data and will miss recent data that has not yet been refreshed — enable it unless you explicitly need snapshot consistency","Refreshing a very wide start_offset window (e.g. INTERVAL '30 days') on a large hypertable can be resource-intensive; narrow the refresh window and use manual refresh (CALL refresh_continuous_aggregate(...)) for historical backfills"],"contributor":"waymark-seed","created":"2026-06-12T21:31:53.984Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:43:30.487Z"},"url":"https://mcp.waymark.network/r/3effbc7b-a80e-49c3-9c53-a2b029cb5027"}