Skip to content
← Browse all courses
Reth topic

Reth Execution Extensions (ExEx)

An Execution Extension (ExEx) is a future that runs inside the Reth node, receives every change to the canonical chain (commits, reorgs and reverts) and tells the node how far it has got. Indexers, rollups and MEV tooling use it to follow the chain without polling RPC.

You install one on the builder with install_exex(id, |ctx| async move { Ok(my_exex(ctx)) }). It has two stages: the closure gets an ExExContext and returns an initialisation future, which resolves to eyre::Result of the ExEx future itself; the node then runs that future, which returns eyre::Result<()>.

API at a glance

ctx.head: BlockNumHash
The head of the chain when the node launched.
ctx.config: NodeConfig<<Node::Types as NodeTypes>::ChainSpec>
The node's config, typed by the node's chain spec (NodeConfig<ChainSpec> on an Ethereum node). ctx.config.datadir() resolves the data directory for the chain, so an ExEx can keep its own state next to the node's.
ctx.notifications: ExExNotifications
The stream of ExExNotification::ChainCommitted { new }, ChainReorged { old, new } and ChainReverted { old }. committed_chain() and reverted_chain() return the chain to apply and the one to undo.
ctx.events.send(ExExEvent::FinishedHeight(num_hash))
Reports the highest block the ExEx has processed. Reth may then prune earlier blocks, so send it only once a block is safe to forget. On a reorg the height can go down.
ctx.notifications.set_with_head(ExExHead { block })
Starts the stream after the ExEx's own head instead of the node's: if the ExEx has processed up to block 10, the first notification is block 11. This is how an ExEx catches up after a restart without resyncing the node.

Checked against paradigmxyz/reth at eb4c15e (2026-04-07): crates/exex/exex/src/context.rs, crates/exex/exex/src/notifications.rs, crates/exex/exex/src/event.rs, crates/exex/types/src/notification.rs, crates/exex/types/src/head.rs, crates/node/builder/src/builder/mod.rs

Lessons on this topic