Your customers’ metrics,
live from your Postgres.
eddy is a hosted analytics database for SaaS products. Write each metric once in SQL, and every commit to your Postgres updates every customer’s numbers. Your app reads them from what looks like one more Postgres database, and agents read them over MCP.
Postgres · commits
account · Northwind #42
Illustration drawn from the product. The 7 ms is measured: a commit in Postgres to every model fresh, on a 7.2M-row snapshot.
01 · The stack
No warehouse, no rollup jobs, no cache to keep in sync.
The usual build for customer-facing metrics is a connector, a warehouse, a schedule, reverse ETL and a cache. eddy replaces all five: hosted like a warehouse, live like your database.
02 · Live
One write, every metric current in 15 ms.
On the demo’s dataset (a store: 60,000 orders, fifteen dbt models), one order placed means one row out, one row in, and every model current. Nothing else is recomputed. See the product up close →
| w | customer_id | name | orders | last_amount |
|---|---|---|---|---|
| −1 | 1 | Ada Lovelace | 6 | 49.99 |
| +1 | 1 | Ada Lovelace | 7 | 49.99 |
Nothing else in the table was touched. Every operator speaks in these weighted rows, which is why an update is never a rebuild.
03 · Per customer
Every customer, their own state.
Shared tables with a tenant column in, a store per customer out: its own state, position and cost. One replication slot for all of them. For SaaS teams →
04 · Agents
Agents read it, act, and watch it move.
Every operation is an MCP tool. An agent reads a metric, asks where it came from, acts through your API, and sees the result on its next step. For agent builders →
get_view account_health · risk = 'high'3 rowsprovenance account_health · id = 5714 seats · 31 eventsrestore_seats(account_id = 57)committedget_view account_health · id = 5705 · Connect
One replication slot, checked before anything is read.
eddy follows your write-ahead log with a role that has REPLICATION and SELECT on the published tables. It creates one publication and one replication slot, and nothing else in your database. Before anything is read, the connection check confirms the slot’s retained WAL is bounded and says how long eddy could be stopped before the slot is invalidated.
In: your Postgres, and product events from Kafka; files on S3 next. Out: a Postgres database your app, psql and Metabase read, an HTTP API, and MCP for agents. Sources and endpoints →
› connect app@db.internal:5432/app checking what eddy needs before it reads anything pass server_version pgoutput, and a slot's WAL can be bounded pass wal_level logical pass max_replication_slots 10, 1 in use by others, 9 free pass replication_role a member of rds_replication pass tables all 12 tables exist in public pass primary_keys all 12 have one pass publication eddy does not exist; eddy will create it pass slot no slot eddy yet; onboarding creates it pass slot_wal_bound max_slot_wal_keep_size = 10.0 GB: eddy can be stopped for 31.4 h before its slot is invalidated 9 passed, 0 warnings, 0 failed · onboarding from one snapshot
06 · Checked
Checked against Postgres after every transaction.
In our test harness and the demo, Postgres or DuckDB recomputes every metric from scratch after every transaction and compares it row for row. These are the numbers that survive it.
Also kept live with corrections included: running balances, sessions, rolling windows, funnels and cohorts, the latest row per key, top-N per group, changing dimensions and hierarchy rollups.
Measured on the demo dataset and eddy’s own harness. eddy is built by Matt Helm at Hollyburn Analytics Inc.
Who it’s for
One engine, a page for each of you.
Get early access.
Tell us a metric you would put in front of your customers or your agents if it were live. We’ll show it staying current on your own schema.
- A reply from a founder within two business days
- A walkthrough on your schema, no slides
- Early access is hosted by us and onboarded with you, by hand
- No mailing list