For developers
Connect eddy to your product.
Connect the source data and define reporting models in SQL or dbt. Then query the results through Postgres, HTTP or MCP, or push them to another system.
01 · The setup
Start with one report.
Bring the source tables and the model behind a customer report. We'll help connect them for an early-access pilot. Your app builds the interface and checks who can access the data.
Connect a source · Preview the SQL model · Choose how to use the results
source app@db.internal:5432 · slot eddy · 12 tables materialized views dbt project · 12 · all ready customers a tenant per account_id · 1,000 postgres postgres://acme.eddy.example:5439/acme http https://acme.eddy.example/api mcp https://acme.eddy.example/mcp readers everyone you invite writers dev@acme.com, ops-agent@acme.com
02 · Sources
Connect the source before loading its data.
Postgres, MySQL, Kafka and webhooks are implemented sources. We'll work through access and hosted setup with you. Each source has a few requirements to check before the first load.
Sources
- PostgresLoad the existing tables, then follow inserts, updates and deletes through logical replication.live
- MySQLLoad tables from MySQL 8.0 or 8.4, then follow the binary log. Values map to Postgres types for your reporting models.live
- KafkaRead product events in Segment's message format. Saved progress lets the reader resume after a restart.live
- WebhooksReceive events signed as Standard Webhooks, Stripe or GitHub. Repeat deliveries are kept once.live
- Files on S3Read Parquet and JSONL files. Built and tested; check availability and load behavior for your hosted pilot.next
- Another sourceTell us where your data lives. We'll work through the connection before starting a pilot.ask
Use the results
- A Postgres databaseUse a Postgres client such as psycopg, SQLAlchemy or psql. Query reporting views in the
eddyschema.live - An HTTP report APIEach view gets a typed HTTP route with filters and pagination. OpenAPI describes the routes; generated TypeScript and Python clients can call them.live
- An MCP serverExpose reporting views as tools. Keep customer read access separate from permissions to change models.live
In
- Postgres
- MySQL
- Kafka
- Webhooks
- Stripe
- GitHub
- Fivetran
- Files on S3next
Read it from
- psql and drivers
- HTTP
- MCP
- Metabase
- Claude
- Cursor
Out
- Postgres
- Kafka
- Webhooks
- Elasticsearch
- OpenSearch
- Iceberg
- turbopuffer
What your Postgres needs.
The connection check tests these settings before loading data. If something is missing, it explains how to fix it.
- wal_level = logicalEnable logical decoding. On RDS and Aurora, set it through the parameter group.
- A free replication sloteddy needs one slot. Adding a table online briefly needs a second.
- A role with REPLICATION and SELECTGrant access to the published tables. A superuser is not required.
- Primary keysPrefer primary keys. The connection check warns when a table needs fallback keys.
- One publication, one sloteddy creates them, or uses a publication you make for it.
- max_slot_wal_keep_sizeLimit how much WAL the slot can retain. The check estimates how long eddy could be stopped before losing its place.
What your MySQL needs.
eddy loads a snapshot, then follows committed changes in the binary log. The connection check tests the required settings first.
- MySQL 8.0 or 8.4Enable row-based binary logging with full row images; full row metadata lets eddy match columns by name.
- A user with the right permissionsGrant replication privileges and SELECT. LOCK TABLES is used briefly to open the initial snapshots.
- Enough binary-log retentionKeep the log longer than an expected outage. The connection check reports how long it is retained and how to change that.
- Reporting SQL and typesValues map to Postgres types. Check differences in string comparison, dates and booleans when reusing MySQL queries.
Kafka uses Segment’s message format today. Files on S3 are built and tested; check hosted availability with us. For warehouse and dbt projects, check the source connection separately from SQL support.
03 · SQL and model support
Define the model in SQL. Preview what it does.
A materialized view is a SQL model whose result eddy stores and updates as source records change. eddy supports familiar reporting SQL, including joins, aggregates and window functions. A preview explains unsupported SQL so you can decide whether a rewrite makes sense.
with revenue as (
select account_id, sum(mrr) as mrr
from subscriptions
where status = 'active'
group by account_id
), usage as (
select account_id, count(*) as events
from usage_events
group by account_id
)
select a.id, a.name, r.mrr, u.events
from accounts a
join revenue r on r.account_id = a.id
left join usage u on u.account_id = a.id
- whereactive subscriptionssource
- group bysubscription accountper account
- group byusage accountper account
- joinaccounts and aggregatesper account
- resultone row per accountmaintained
04 · Querying the results
Check access, then get the customer's data.
Your app checks the user's identity and permissions before selecting their account. The example below uses a Postgres client. The HTTP report API and MCP tools can query the same reporting models.
// Authenticate and authorize in your product before selecting scope. const account = await authorizeReporting(user); const { rows } = await eddy.query( `select day, revenue from account_daily where account_id = $1 order by day desc limit 90`, [account.id] ); res.json(rows);
Also · Sending results
Push the data to where you need it.
A sink sends a model's results to another system. Use one to keep a Postgres table, Kafka topic, webhook receiver or supported search destination updated. Webhook notifications can also tell your backend which customer's data changed.
05 · Changing models
Change a model while the system is running.
Preview new models and review replacements before applying them. Use the console, API or an authorized coding agent to make the change.
- 01 · write
Bring your SQL or dbt models
Bring a compiled dbt manifest or a folder of SQL. Preview each model to check what eddy supports.
- 02 · preview
Preview the model
preview_materialized_viewshows the output and explains unsupported SQL before you build. - 03 · review
Review a replacement
review_materialized_view_changechecks both definitions in Postgres. See which rows change and what needs rebuilding. - 04 · apply
Apply the change
The new view builds beside the running system and swaps in between update batches. The command history records who requested it.
- 05 · read
Use the result
Query through Postgres, the HTTP report API or MCP. Each read uses one snapshot and reports which source changes it includes.
- 06 · debug
Inspect a result
Inspect contributing rows where supported, or trace a source transaction through the parts of the model it changes.
06 · Investigating a report
Find out why a number changed.
Check which source changes the result includes. Trace a transaction through the model, or inspect contributing rows where supported.
How far the data has updated
Check source progress and model status. See the graph.
Contributing rows
See current rows behind a result where supported. Inspect a number.
Time and alignment
Choose when inputs advance together and how as-of queries work. Time and alignment.
07 · Coding agents
Let a coding agent work on your models.
Connect Claude, Claude Code or another MCP client to eddy. Authorized writers can preview, create and replace models, then check when they're ready. Keep those permissions separate from customer reporting tools.
Example session; timing is illustrative. The tools follow the OpenAPI, and the command history records who requested each change.
$ claude mcp add --transport http eddy https://acme.eddy.example/mcp signed in through AuthKit · writer › add a materialized view for weekly active seats per account ▸ eddy.get_catalog 12 materialized views · 6 tables ▸ eddy.preview_materialized_view refused unsupported correlated subquery · try a join ▸ eddy.preview_materialized_view ok · 3,112 rows · 9 operators ▸ eddy.create_materialized_view command 312 · hydrating ▸ eddy.get_command 312 ready · built in 3.0 s, still ticking ▸ eddy.query select * from eddy.weekly_active_seats … Added weekly_active_seats. Rewrote the subquery as a join.
Keep going
Let's look at the report you're building.
Book a demo and bring your schema and reporting model. We'll work through the source connection and how your product will use the results.

