solution · real-time analytics

Your dashboard is a query.
Not a pipeline.

GROUP BY, HAVING and window functions run directly on the operational store — the rows your app just wrote. There is no export to a warehouse, so there is no copy to lag behind.

write, then aggregate
> POST /v1/tenants/:t/rows/orders
> { "sku": "s_412", "qty": 3, "price": 79, "country": "DE" }
committed ✓

> SELECT country, SUM(qty * price) AS revenue
  FROM orders GROUP BY country
  HAVING SUM(qty * price) > 10000
  ORDER BY revenue DESC;

country   revenue
US        128,940
DE         61,205   ← includes the row above
JP         44,310

same store · no export job · fresh at read time
the problem

Every hop between the write and the chart is staleness you chose.

The conventional path to a live dashboard is a pipeline: copy the operational data somewhere analytical, then query the copy. Each stage adds a schedule, a schema, and a failure mode — and the sum of the schedules is how far behind your numbers run.

01
Export

A batch job or CDC stream copies rows out of the operational database. It runs on a schedule — and everything downstream inherits that schedule.

the copy is born stale
02
Transform + load

The copy lands in a warehouse with its own schema, its own types, its own failure modes. Schema drift breaks it quietly; backfills patch it loudly.

a second schema to keep true
03
Read the copy

The dashboard answers questions about the state of the copy, not the state of the system. The gap between the two is the lag your users see.

lag = the age of the copy

OriginChain removes the hop instead of speeding it up. The aggregate runs where the write landed — on the same hash-keyed substrate your application writes to — so the dashboard's question and the system's state are the same data.

how it works

The analytical SQL, on the operational rows.

Operational counters, live leaderboards, cohort splits, aggregate alerts — the queries behind them are three families of construct, and all three ship on the SQL surface today.

Aggregates
GROUP BYSUM / AVG / MIN / MAX / COUNTCOUNT(DISTINCT)SUM(qty * price)HAVING + OR

A streaming aggregate executor. Aggregates wrap any expression, not just bare columns — SUM(qty * price), AVG(score - baseline). HAVING composes with OR.

Window functions
ROW_NUMBERRANK / DENSE_RANKLAG / LEADSUM…COUNT OVER

A streaming partition walk on top of the index scan — no spool, no extra storage. Live leaderboards and running totals are one clause, not a nightly job.

Predicate pushdown
WHEREindexed columnsconjunct splittingEXPLAIN ANALYZE

The planner splits conjuncts and routes each to the cheapest secondary index, so WHERE on indexed columns avoids full scans. EXPLAIN ANALYZE shows the chosen path.

the plan, measured

Every aggregate plan: estimated vs actual, per node.

EXPLAIN ANALYZE returns the chosen plan with estimated and actual row counts plus cost per node. When the two drift apart, you've found the slow dashboard query in one response — without instrumenting the dashboard itself.

Below, the planner pushed the country predicate down to a secondary index, so the aggregate reads the index range instead of scanning the table.

explain analyze
> EXPLAIN ANALYZE SELECT country, COUNT(*) … GROUP BY country;

group_aggregate (by country)   est 5 · actual 5 · 23.1 ms
└─ index_scan orders(by_country) est 18.4k · actual 18.4k · 18.4 ms

point lookup < 5 ms · GROUP BY 10k < 50 ms
why fresh is structural

No copy to lag. No sync to break.

Every shape — rows, vectors, full-text postings, graph edges — commits in one atomic write on a single substrate. For analytics that means the aggregate can never read a state where the copy hasn't caught up, because there is no copy: the write that just returned is in the next GROUP BY, by construction.

When polling isn't enough, /watch streams every write the instant it lands — a reactive feed for the counters and alerts that should push, not poll. The full picture is on the architecture page.

one store, two paths
write path
  app ── write ──▶ substrate            ✓ committed

read paths — same substrate, no copy in between
  dashboard ── GROUP BY / HAVING ──▶ substrate
  alerts    ── /watch stream     ──▶ substrate

the warehouse detour this replaces:
  app ─▶ db ─▶ export ─▶ transform ─▶ warehouse ─▶ dashboard
at a glance
0
copies between the write and the query
< 50 ms
GROUP BY over 10k rows
< 5 ms
point lookup
32
tables per join, left-deep planner
what we are not

Not Snowflake, not BigQuery. Multi-TB columnar scans across years of archives belong in a warehouse. Our sweet spot is operational analytics over live data — where the latency budget is milliseconds and the data is the state of your product right now.

next

Point a GROUP BY at your live data.