How do I get blockchain data into Postgres?
Updated August 2026
Run a Substreams SQL sink against your Postgres instance. You define the table schema, write a module that emits matching rows, and point the sink at a connection string — it backfills history and then keeps streaming.
The sink maintains a cursor table so a restart resumes at the exact position rather than re-processing or skipping blocks.
Do I have to run the sink myself?
No. Hosted Sinks runs it for you — configure a package and your Postgres connection details on The Graph Market and it indexes continuously, with no infrastructure on your side. There are documented walkthroughs for Supabase and Neon.
It is in beta, and your database must be reachable from the internet. If that rules it out, or you want the sink co-located with your database, run it yourself as below. Either way the Substreams package is identical.
What do I need to set up?
A schema. A schema.sql defining your tables. The sink will not infer this — the tables must exist and match what your module emits.
A module. Most packages from the registry already work with the SQL sink out of the box — you rarely need to write your own. When you do, the substreams-sql agent skill generates both the schema and the module from a description of what you want.
A DSN. The Postgres connection string. Getting the scheme and parameters right is a common early stumbling block.
An API key. From thegraph.market, no personal information required.
Which output pattern should I use?
| Database changes (CDC) | Relational mappings | |
|---|---|---|
| Emits | Row-level inserts, updates, deletes | Normalised tables with relationships |
| Best for | Real-time consistency, mutable state | Analytical querying, joins |
| Reorg handling | Rows corrected in place | Rows corrected in place |
CDC suits data where records change — positions, balances, current state. Relational mappings suit append-heavy event data you will query analytically.
What are the common mistakes?
These come up repeatedly in Database Changes (CDC) mode and are documented in the deployment skill — relational mappings mode applies its own schema and doesn't share these two:
Wrong protobuf type. In CDC mode, the sink expects a specific output type from your module. A mismatch fails immediately, which is at least easy to diagnose.
Missing schema.sql or domain tables. In CDC mode, the sink does not create tables for you.
Primary key mismatch. If your module emits a composite key that does not match the table definition, writes fail or silently conflict. Blockchain data often needs composite keys — transaction hash plus log index, for example — and getting this wrong is the most common real problem.
Batch flush tuning. Defaults are conservative. For large backfills, tuning the flush interval makes a substantial difference to throughput.
Does this actually work end to end?
Yes, and it has been tested publicly. In StreamingFast's published evaluation, an AI agent built a complete, production-ready Substreams-to-Postgres pipeline from a plain-English prompt and matched the golden reference exactly — including working through DSN scheme and composite-primary-key issues along the way.
How do I handle the backfill?
Specify a start block and let the sink run. Historical processing happens in parallel, so a large range completes far faster than block time, and the sink transitions to live streaming automatically when it catches up.
For very large backfills, load into a staging table and swap, rather than writing into a table serving live queries.
Frequently asked questions
Will reorgs corrupt my tables? No, provided you use a sink that tracks cursors. Reorged blocks are signalled and affected rows are corrected.
Can I use a managed Postgres? Yes — RDS, Cloud SQL, Supabase and similar all work. You need network access and write permissions.
How do I add a column later? Alter the table, update the module, and re-run from the block where the new field matters.
Get an API key at thegraph.market — no personal information required.
Related: How do I stream onchain data to a database? · How do I get blockchain data into ClickHouse? · How do I backfill historical blockchain data?