Real-time dashboards & user-facing analytics
Serve user-facing analytics from continuously-materialized tables. A change propagates to the serving table in microseconds, so dashboards are live — not polled.
The problem
Why this is hard today
User-facing analytics has a latency budget a data warehouse cannot meet: the dashboard has to load in milliseconds, for thousands of concurrent users, over data that changes constantly. Running the aggregation on every page load does not scale; running it on a cron and caching the result serves stale numbers.
The usual fix — a stream processor that maintains rollups into a serving store — adds a second system, a second schema, and a freshness gap between the rollup and the source that users notice the moment they act and refresh.
What user-facing analytics needs is a serving table that stays continuously fresh from the source, updated by event propagation rather than a re-scan timer, and read as an ordinary indexed table.
Architecture
How NYXDB does it
A continuous transform materializes the serving table and keeps it fresh through PSI event routing (ADR-080): a committed change propagates to the subscriber in a flat ~2.56µs regardless of table size, so the serving table is never more than microseconds behind the source.
- 01
Define serving table
A keyed table holds the pre-aggregated shape the dashboard reads.
- 02
Materialize
CREATE TRANSFORM … INTO serving AS SELECT … maintains it incrementally.
- 03
Propagate (PSI)
Only matching changes route to the transform — a flat ~2.56µs event→subscriber path, not a periodic full re-scan.
- 04
Serve
Dashboards read the serving table as an ordinary point/range read; STREAM SELECT pushes live updates.
Real SQL
In practice
CREATE TABLE dashboard_tiles ( tenant String NOT NULL, metric String NOT NULL, value Float64, PRIMARY KEY (tenant, metric)) SETTINGS mode='keyed', layout='row', storage_policy='memory_data';CREATE TRANSFORM roll_tiles INTO dashboard_tiles ASSELECT tenant, metric, sum(amount) AS valueFROM eventsGROUP BY tenant, metric;SELECT metric, value FROM dashboard_tiles WHERE tenant = 'acme';STREAM SELECT metric, value FROM dashboard_tiles WHERE tenant = 'acme';Every statement follows the engine’s own test SQL shapes. See the SQL reference for full syntax.
Capabilities
What you get
Continuous materialization
CREATE TRANSFORM keeps serving tables fresh (ADR-080).
~2.56µs propagation
Flat event→subscriber latency, empty to a 2M-row tail.
Point-read serving
Dashboards read pre-aggregated keyed tables in O(1).
Gap-free recovery
Transforms resume from their reflected position after restart.
Exact aggregates
Rollups are exact — no double-counting.
Live push
STREAM SELECT drives real-time UI updates without polling.
Proof
Measured on the vetted benchmark lane
event → serving-table propagation, flat
empty to a 2M-row tail
vetted table
View benchmark268nskeyed serving read, O(1)
flat 1k–16k keys
vetted table
View benchmarktransform recovery from reflected position
ADR-080
Measured on AMD EPYC 9554P 64-Core Processor (64t), 1505GB RAM, 6x NVMe — measured on server-class hardware. Release build, median of 5 (re-captured stragglers: median of 3), commit-pinned (7945ae33, 2026-07-09). Ingest figures are engine-side. See the full benchmark suite.
Learn more
Related documentation
Dashboards that are live, not polled
Materialize a serving table and stream it to the client.