How it works
A sequencer normally executes an entire block and publishes it once, at the end of the block time. Subblocks split that window: the sequencer publishes what it has executed so far every 200 ms, and each subblock extends the previous one. Two properties follow from that, and both matter to anyone consuming the stream.- A subblock sequence is append-only. The sealed block’s transaction list is the concatenation of every subblock in the sequence, in order. Transactions already emitted in a subblock are never reordered or dropped from the block that seals them. On a chain running Lagoon, the sealed block may also end with a post-execution transaction that the stream carries separately — see the post-execution transaction.
- A subblock is a projection, not a commitment. It reports the transactions executed so far. It does not prove the resulting state.
What a subblock payload carries
The payload is wire compatible with the Flashblocks format that preceded it, and the type is still namedExecutionPayloadFlashblockDeltaV1.
No field was removed, and the only addition is the optional post_exec_tx described below.
Four fields are present but set to their zero value:
Every other field carries a real value, including
transactions, gas_used, receipts_root, and logs_bloom.
The state root is the root cause.
It is computed while execution continues and is only exact once the block is sealed, so a subblock cannot carry it.
A block hash commits to the state root, so it cannot be final either.
A node that consumes the stream does not need the zeroed fields.
It executes the subblock’s transactions against its own view of the chain and serves the result under the pending block tag, so eth_call and eth_getBalance answer correctly without any root on the wire.
The post-execution transaction
From the Lagoon network upgrade, a block may end with a post-execution transaction of type0x7D, which carries sequencer-provided consensus data such as per-transaction gas refunds.
The stream carries it in diff.post_exec_tx, holding the transaction’s encoded bytes, and never inside diff.transactions.
It sits outside transactions because it is not fixed the way a transaction already streamed is.
It is computed from everything the block has executed so far, so the sequencer recomputes it for each subblock, and each subblock’s value replaces the previous one.
Putting a value that still changes into an append-only list would publish a transaction that a later subblock contradicts.
So if you read the stream directly, treat diff.post_exec_tx as mutable rather than as one more streamed transaction.
Concatenating diff.transactions across a block’s subblocks gives you the sealed block’s transaction list, excluding the final 0x7D transaction if one is present.
The Lagoon post-exec specification is normative for this field and is the reference to build against.
It specifies why the field lives in
diff, when it is absent, which subblock’s value is canonical, that transactions may be empty, and why no receipt is streamed for it — each rule paired with its rationale and with what a consumer may assume.
The Subblocks specification covers the same field from the stream’s side.Architecture
Subblocks are produced by the sequencer’s execution client as it builds the block, and published over a WebSocket stream. Nothing sits between the consensus layer and the execution layer.op-nodedrives block building through the engine API, exactly as it does on a chain without subblocks.- The execution client executes the block and publishes a subblock every 200 ms while it does so.
flashblocks-websocket-proxyrelays the stream from the active sequencer to RPC providers.op-conductor(optional) manages a multi-sequencer setup so only the healthy leader’s stream reaches the proxy.
The Flashblocks stack
Before subblocks, pre-confirmations were produced by the Flashblocks stack:rollup-boost coordinating between the consensus layer and two execution clients, with op-rbuilder building blocks and op-reth standing by as a fallback builder.
For availability information, see Enabling Subblocks.
Subblocks FAQ
Block building and availability
How often are subblocks produced?
How often are subblocks produced?
Every 200ms, but configurable to lower values.
OP Sepolia and OP Mainnet both move to 200 ms; see the Subblocks notice for the rollout dates.
Will a block always contain the maximum number of subblocks?
Will a block always contain the maximum number of subblocks?
No. Heavy execution in one interval reduces the time available for the ones after it, so the count varies between blocks.
Do large transactions get delayed?
Do large transactions get delayed?
A large transaction can land in any subblock with enough gas capacity left, so in practice it lands later in the block.
See Subblocks and gas usage for a worked example.
Safety and continuity
What happens if the sequencer fails mid-block?
What happens if the sequencer fails mid-block?
The subblocks already published for the abandoned block do not seal.
In a multi-sequencer setup,
op-conductor transfers leadership to a healthy sequencer, and the stream continues from the new leader through the same endpoint.
For details, see the op-conductor documentation.Do subblocks change the safety model of the chain?
Do subblocks change the safety model of the chain?
No. Every transaction in a subblock is executed by the same engine, under the same rules, as it would be in a block. Subblocks change when the sequencer tells you the outcome, not what the outcome is.
Can a pre-confirmation be revoked?
Can a pre-confirmation be revoked?
Yes, under the same conditions that let the sequencer reorg an unsafe block. A pre-confirmation carries the sequencer’s trust assumption, not the protocol’s. See Transaction finality for what each stage guarantees.
What does a pre-confirmation response contain?
What does a pre-confirmation response contain?
The transactions executed so far in the block, their receipts, and the cumulative
gas_used, receipts_root, and logs_bloom.
It does not contain a usable state_root or block_hash — both are zeroed, as described in what a subblock payload carries.
It also does not contain the block’s post-execution transaction or a receipt for it; that transaction is streamed separately in diff.post_exec_tx.Next steps
- Read pre-confirmed state from your app with the Subblocks integration guide.
- Check the Subblocks notice for rollout dates and the payload fields to audit.
- Learn how subblocks change gas availability within a block.