Deep dive · Runtime · 18 min

How Sealevel schedules parallel work.

A single open volume on a reading desk, lit by a warm window

The Sealevel scheduler is the part of the runtime that decides which instructions inside a block can run at the same time. Most runtimes take a global lock and execute one thing at a time; Sealevel reads the accounts each instruction touches and runs the ones that do not conflict together. This dive explains how that decision is made, where it breaks down, and what a builder should assume about it.

Why a global lock is avoided

A block on this chain can carry thousands of instructions. If each had to wait for the one before it, a block would take far longer than the slot allows. Sealevel instead groups instructions by their read-write sets and dispatches the non-conflicting groups to many cores at once. The constraint is not the number of cores; it is the shape of the conflict graph.

How the decision is made

For each instruction the runtime looks at the accounts declared in the transaction. It records which are read and which are written. It then walks the instructions in order and, for each, checks whether any account it touches has already been written by an instruction placed in the current parallel batch. If not, the instruction joins the batch; if so, it waits for the next batch.

The order matters. Two instructions that touch the same writable account cannot run together, but the one placed first in the block is the one whose write the later one sees. A builder who relies on a particular write order must encode it in the transaction, not hope for it from the scheduler.

Where it breaks down

The scheduler can only see the accounts a transaction declares. If a program reads an account the transaction did not list, the runtime cannot protect it. Programs that touch shared state through an undeclared account are the classic source of "this should have been safe" surprises. The fix is on the program side: declare every account you touch.

There is also a subtlety the first version of this dive glossed over: when several instructions want to write the same account, the scheduler must pick one to go first. The choice follows the block's instruction order, not the size of the write or the gas paid. A reader who expected a "highest-fee-first" rule was rightly confused; there is no such rule here.

What to assume as a builder

Assume that instructions touching disjoint accounts can and will run together, and that instructions touching a shared writable account will run in block order. Do not assume timing beyond that. If two of your instructions must see each other's writes, put them in the same transaction in the order you need, or use a single instruction that does both.

Three questions before you turn the page

  • Two instructions both read account A and both read account B. Can they run together?
  • One instruction writes account C; a later one reads account C. What does the later one see?
  • Your program reads an account the transaction did not declare. What can go wrong?

Last reviewed for the current client release. Updated notes are dated at the bottom of the page.