Skip to main content

Ponder: A Faster, TypeScript-Native Way to Index EVM Blockchain Data

· 9 min read
Sivabharathy

Every dApp I've ever worked on eventually hits the same wall: reading data back out of the blockchain. Writing to a contract is the easy, glamorous part. Then someone asks for a page that shows "all the user's past transactions, sorted by date, with token metadata," and you remember that the chain is a terrible database. You can't just SELECT * FROM transfers. You have to index — replay events, shape them into tables, and keep them in sync as new blocks arrive. For years the default answer to that was a subgraph on The Graph. Ponder is a bet that there's a much nicer way to do it, and after spending time with it, I think the bet mostly pays off.

What is Ponder?

Ponder is an open-source TypeScript framework for indexing EVM smart contract data. You point it at some contracts, describe the shape of the data you want, write a bit of logic to transform on-chain events into rows, and it gives you back a queryable API — GraphQL and SQL — that stays in sync with the chain. It's built by Cantrip, Inc. and it's fully open source.

If you've used The Graph, the mental model is similar: define a schema, write handlers for contract events, get an API. The difference is in the details, and the details are where indexing tools have historically made developers miserable. Ponder's whole pitch is that indexing should feel like building a normal backend app — with type safety, hot reloading, and no arcane code generation step — instead of fighting a specialized pipeline.

Why indexing is such a pain

Before I get into how Ponder works, it's worth being honest about the problem, because if you haven't done this you might not appreciate why a whole framework exists for it.

Smart contracts emit events. Those events are the breadcrumbs of what happened — a transfer, a swap, a mint. But they're scattered across millions of blocks, they're not queryable in any useful way, and reading them directly over RPC for anything non-trivial is painfully slow and expensive. So you build an indexer: a service that crawls historical blocks, processes each relevant event, writes the result into a real database, and then keeps following the chain head so your data never goes stale.

Do that naively and you'll spend weeks on the boring, error-prone parts: handling chain reorganizations, resuming after a crash, backfilling efficiently without burning through your RPC provider's credits, and keeping the whole thing type-safe so a schema change doesn't silently break three handlers. This is the swamp Ponder is trying to drain.

How Ponder actually works

The thing I appreciate most is how little ceremony there is. A Ponder project is basically three pieces.

The config (ponder.config.ts) is where you declare which chains you're indexing, your RPC endpoints, and which contracts to watch — including the ABI and the block to start from. It even supports factory patterns, so you can index every child contract a factory deploys without hardcoding addresses.

The schema (ponder.schema.ts) is where you define your tables — the shape of the data you want to end up with. Because it's TypeScript, the tables you define here flow through the entire app as types. Change a column and your editor immediately tells you which indexing function no longer compiles. That end-to-end type safety is not a small quality-of-life thing; it's the difference between confident refactors and praying.

The indexing functions (in src/) are plain async functions that run for each event. You get a fully typed event object and a typed database handle, and you write normal code: read the event args, maybe fetch some extra on-chain data, and insert or update rows. That's it. No special query language, no generated glue you have to regenerate every time something changes.

Once it's running, Ponder serves your data through an auto-generated GraphQL API and also lets you query the underlying tables with SQL over HTTP. So your frontend or backend can talk to it however it prefers.

The performance story

Ponder's headline claim is speed, and the numbers the team publishes are genuinely eye-catching. In their benchmark — indexing the Rocket Pool ERC-20 contract across roughly 118,000 mainnet blocks on an M1 MacBook Pro — Ponder came out around 10x faster than an equivalent Graph subgraph.

The specifics are worth sitting with. A cold sync (starting from scratch) finished in about 37 seconds versus around 5.5 minutes for the subgraph. A warm/cache sync took 5 seconds versus over a minute. And it did all this while using dramatically less: about 31 MB of database space against The Graph's 1.1 GB, and fewer RPC credits (108k vs 167k) to get the same result.

Now, I always treat vendor benchmarks with a healthy dose of salt — they pick the scenario, after all, and your mileage on a gnarlier multi-contract index will differ. But the shape of the result matches my own experience: subgraphs feel heavy, and the iterate-wait-iterate loop during development is genuinely slow. Even if the real-world multiplier is smaller than 10x, "meaningfully faster with a fraction of the footprint" is a big deal when you're re-syncing an index for the tenth time in an afternoon.

The developer experience is the real selling point

Speed gets the headline, but the reason I'd actually reach for Ponder is the day-to-day feel.

Hot reloading means you edit an indexing function and it re-runs locally without a full restart — the same tight feedback loop you'd expect from a modern web framework, which is shockingly rare in blockchain tooling. No code generation means there's no separate build artifact to keep in sync; the types just exist. And because it's a normal Node.js app under the hood, you deploy it like any other service — one-click to whatever Node environment you already use, with support for horizontal scaling and zero-downtime updates.

Put together, it collapses the distance between "blockchain indexing" and "a backend I already know how to build and operate." For a full-stack engineer who doesn't want to learn a bespoke deployment pipeline, that's the whole game.

Ponder vs The Graph: the honest comparison

It would be easy to frame this as "Ponder wins," but that's too glib, because they're not quite the same kind of thing.

The Graph is a decentralized protocol — a network of indexers you can publish a subgraph to, so nobody has to run infrastructure and the data has a censorship-resistant, trust-minimized home. That decentralization is a real, sometimes essential property, especially for a protocol that wants its data layer to outlive any single operator.

Ponder is a framework you run yourself. There's no decentralized network; you host the process, you point it at your own RPC provider, you own the database. That's simpler and faster and more flexible — and it also means you're responsible for uptime, and you don't get the trust-minimization story. For most application backends, that trade is completely fine; you were going to run a server anyway. For a protocol that specifically wants decentralized, verifiable data, The Graph still makes sense.

So the real question isn't "which is better" — it's "do I need a decentralized data network, or do I need a fast, pleasant indexer for my app?" Most teams building a product need the second.

The pros

  • Developer experience is excellent. Hot reload, no codegen, and it feels like building a normal TypeScript backend.
  • End-to-end type safety. Your schema types flow through every indexing function, so refactors are safe and autocomplete just works.
  • Fast, with a small footprint. The sync speed and tiny database usage genuinely change how iterative development feels.
  • Deploy anywhere. It's a Node app — no special hosting, easy to fit into infrastructure you already run.
  • Flexible querying. Both GraphQL and SQL over HTTP, so you're not boxed into one access pattern.
  • Multi-chain and factory support. Index across chains and dynamically deployed contracts without hardcoding.
  • Open source. No lock-in; you can read the code and self-host with full control.

The cons

  • You own the infrastructure. No decentralized network means uptime, scaling, and backups are your problem. That's a feature for control and a cost for convenience.
  • You still need a good RPC provider. Indexing is only as fast and reliable as the node you're reading from; a rate-limited free endpoint will bottleneck you.
  • No trust-minimization. If your use case specifically needs decentralized, verifiable data, a self-hosted framework isn't the answer — The Graph's network is.
  • Younger ecosystem. The Graph has years of subgraphs, tutorials, and community answers. Ponder is newer, so you'll lean more on its docs than on a decade of Stack Overflow.
  • EVM-only. It's built for EVM chains. If your world includes non-EVM ecosystems, this won't cover them.

Who should use it, and my verdict

Ponder is a strong fit if you're building an application backend that needs on-chain data and you're comfortable running a small service. Startups, dApp teams, analytics dashboards, anyone who's felt the slow, heavy grind of subgraph development — this is aimed squarely at you. If you already live in TypeScript, the ergonomics will feel like coming home.

I wouldn't reach for it if your requirement is specifically a decentralized, trust-minimized data layer; that's not the problem it solves, and pretending otherwise would set you up for disappointment.

But for the very common case — "I'm building a product, I need to read my contracts' data quickly, and I want to do it without learning a whole alien pipeline" — Ponder is one of the more genuinely pleasant tools I've tried in this space in a while. The best endorsement I can give a piece of blockchain infrastructure is that it got out of my way and let me build. Ponder does that, and it does it fast.