Kourier Was Right

Years ago Project Kourier made the rounds in the Stacks ecosystem. It was a proposal, not a product: break the monolithic API into primitives. An immutable raw event layer at the bottom, transformation on top, and let developers build their own views of chain data instead of hoping the general-purpose API happens to have the query they need. "The Graph, but even better" was the pitch.

I read it and thought: yes, obviously. Then nobody built it. As far as I can tell nobody even tried.

I spent three years at Hiro, close enough to the API that ran the ecosystem to feel every pain point Kourier named. They weren't hypothetical:

You need a node to do anything custom. Want data the API doesn't serve? Run a Stacks node, learn its event firehose, build ingestion, handle reorgs. That's infrastructure work before you've written a line of your actual app.

A general-purpose API can't be your API. The endpoints are someone's best guess at what everyone needs. The moment your app needs a custom view (this contract's events, joined this way, aggregated like that) you're either making N requests and joining client-side or you're back to running a node.

Schemas change, data doesn't re-sync. Realize your indexer needs one more field? Hope you kept the raw events. Most setups didn't, because the raw layer and the transformed layer were the same layer.

Real-time is an afterthought. Polling an HTTP API to build anything live. Polling!

Kourier's insight was that these are all the same problem. Raw chain events are immutable facts, everything else should be a view derived from them. Rebuildable, streamable, yours. Separate the layers and each one gets simple.

That's secondlayer. The shape is exactly the one the proposal drew, with a few years of hindsight applied.

Index is the zero-infra layer. Curl decoded chain data, no API key, no node:

Terminal
curl https://index.secondlayer.dev/sbtc/supply
# { "total": "3841.22", "unit": "sBTC" }

Subgraphs are the custom views. Write a one-file TypeScript indexer, deploy it, get Postgres and a REST API back. Ingestion, reorg detection, and backfill are handled. And because the raw events are kept, "add a field and re-sync" is an actual operation instead of a data-loss incident.

Terminal
secondlayer deploy ./subgraph.ts

Streams is the firehose itself, for when you'd rather build your own.

And the part I care about most: docker compose up runs the same code we host. Not a crippled community edition, the same indexer, Postgres, and API on your hardware. Kourier imagined community-run instances as a design goal and I wanted to take that part seriously.

I didn't come up with the ideas here. I just stood on their shoulders and had some fun with it.