Call Handlers & Block Handlers
When start building subgraphs, indexing feels simple. A contract emits a Transfer event, your subgraph caches it, saves it, done.
Events are the easy, cheap, recommended way to index. But sometimes events aren’t enough.
Two Other Data Sources a subgraph can react to:
Call handler: A function being called on the contract — even it emits no event. Example: Someone calls transfer(to, amount).
Get Jevin Jojo’s stories in your inbox
Join Medium for free to get updates from this writer.
Block handler: A new block being produced. Example: Snapshot total supply every 100 blocks
- Call Handlers — You watch the raw functions calls going into the contract, whether or not it emitted anything.
- Block Handlers — You don’t care about a specific interaction at all, you want to run code on schedule (per block, or every N blocks) to take snapshots/aggregate.
Call handlers & block handlers require an archive node / trace API, and are NOT supported on all Networks.
Call handlers & non-filtered block handlers rely on Ethereum trace APIs. It means they only supported on certain networks. (many chains and L2s do NOT support call handlers at all).
When to use Each Type:
- If we need to capture a specific function being called and it’s arguments? → Use a call handler
- Periodic snapshots/aggregate regardless of any single interaction (e.g.: TVL every 100 blocks) → Use handler with
polling. - One-time initialization before anything else runs → Use a block handler with
filter: {kind: once}.









