Skip to main content

Introduction

This document covers the operational side of activating MIP-8: migrating a node’s database from slot to page encoding, live and without resyncing from genesis. Each node dual-writes both encodings until the fork flips the network to page-encoded database, then drops the old slot-encoded database.

Background

MIP-8

MIP-8 reorganizes the EVM state trie to be page-aware: storage slots are grouped into 4 KB pages instead of being scattered independently across disk by hashing. For node operators, what matters is that this changes the on-disk trie layout — which is why a migration is required.

TrieDB timelines

A timeline is a full copy of the trie state on disk, built by writing every committed block into it in a given encoding. A node can run one or two timelines at once, each in its own encoding:
  • Slot-encoded timeline uses the current trie layout, where each storage slot’s disk location is determined independently by hashing. This is the pre-MIP-8 format.
  • Page-encoded timeline uses the MIP-8 layout, where slots are packed into pages of 128 consecutive slots. This is the post-MIP-8 format.
Dual mode is a transitional state where a node runs both encodings at once, as two timelines on disk, and writes every committed block to both. A node stays in dual mode for the whole window between activating the page timeline and decommissioning the slot timeline. Primary and secondary just label the two timelines on disk. They have no effect on execution or consensus. Over the course of the migration, primary and secondary swap, then the secondary is dropped (see Migration plan).

State machine kinds

The node’s database tooling (monad-mpt, monad-cli) refers to slot and page encoding as state-machine kinds: What matters for execution is which timeline is canonical versus shadow. The canonical timeline is the one whose state_root is used for blocks on the canonical chain; the shadow timeline computes the same blocks on the other encoding in parallel, without its state_root being used anywhere. MIP-8 activation is exactly the flip between the two:
  • before activation, ethereum (slot) is canonical and monad (page) is the shadow
  • this swaps at the hard fork, monad (page) becomes canonical and ethereum (slot) becomes the shadow.
This is why activation happens by network-wide consensus.

Migration plan

The migration runs in three phases: two operator actions and one hard fork. Phase A activates the page timeline on each node. Phase B is the MIP-8 hard fork: at a fixed timestamp, the canonical chain switches from the slot timeline to the page timeline. Phase C decommissions the now-legacy slot timeline.
1

Initial

DB mode is Legacy/Slot — a single slot timeline. Execution is Pre MIP-8 Activation.
2

Phase A — Page activation

Operators activate the page secondary, bringing DB mode to Dual. Execution is still Pre MIP-8 Activation — nothing changes at the execution level yet.
3

Phase B — Hard fork

At the fork timestamp, MIP-8 activates network-wide: the page timeline becomes canonical and the slot timeline becomes its shadow. The node stays in Dual mode.
4

Phase C — Slot decommission (Final)

Operators promote the page timeline as primary, and decommission the now secondary slot timeline. DB mode flips to Page — a single page timeline. The node is now fully migrated.

Operations

Network status

Get the current status

Check a node’s current on-disk state directly with monad-mpt:
Legacy/Slot — migration not started:
Dual — migration in progress:
Page — migration complete:

Prometheus Metrics

You can monitor the dual-DB migration phase via the Prometheus metric monad_triedb_migration_phase:
  • 0: slot-encoded (expected value during Init phase)
  • 1: dual-mode (expected value during Phase A and Phase B)
  • 2: page-encoded (expected value during Phase C)

Monad Status

The monad-status script has been updated to reflect the TrieDB mode, e.g.:

Hard reset a node

The hard reset process itself doesn’t change — still follow the Hard Reset Instructions. The DB mode logic below happens automatically inside that same restore-from-snapshot step; there’s no new manual procedure to learn. A hard reset doesn’t migrate your existing database — it wipes it and rebuilds from a snapshot. That means the reset tooling can’t look at your node’s prior on-disk state to decide what to rebuild (the reset truncates the DB before anything else runs), so it picks the target DB mode with this logic:
  • If the MIP-8 hard fork has already passed, it creates a page timeline only, and imports the snapshot into it.
  • If the fork hasn’t passed yet and it can also create a page timeline, the result is Dual mode, with the snapshot imported into both timelines.
  • If the fork hasn’t passed yet and it can’t create a page timeline, the result is Legacy/Slot, with the snapshot imported into the slot timeline only.
The first row is deliberate: once MIP-8 is active on the network, there’s no reason to stand up a slot timeline just to decommission it again in the very next phase — a reset node goes straight to page-only.

Migration tasks

This applies to both full nodes and validators. The migration runs in three phases. Phases A and C are actions you take on each node; phase B is a network-wide hard fork that happens on a schedule.

Phase A - Page activation

Do not run this procedure. Wait for the official Monad Foundation announcement.Validators migration will occur in cohorts. Ensure you know which cohort you are in, and only action these steps when your cohort is announced. Deployment dates and cohorts will be communicated via official channels.
This process is supported starting from 0.15.2. This step uses the new monad-mpt and monad-cli binaries starting from this version. Stop the monad services:
The snapshot dump will open many file descriptors (8 per shard). If your system’s open-file limit is at the default 1024, the dump will crash. Raise the limit before running:
Prepare the snapshot folder and clean up any pre-existing secondary timeline:
Activate the secondary timeline:
Expected output: Activated secondary timeline; stamped state-machine kind. Dump a snapshot of the current primary:
Expected output: snapshot dump success=true. Takes approximately 5 minutes. Load the snapshot into the page secondary:
Expected output: load_to_secondary=true. Takes approximately 3 minutes. Clean up the snapshot:
Verify the status of TrieDB:
The command should print output similar to the following:
Verify that the latest values for both timelines are close (47536183 in this example):
  • Primary: latest is 47536183
  • Secondary: latest is 47536183
A difference of a few blocks (up to ~10) is normal. Start the Monad services:
All services should show Active: active (running). Confirm the node rejoins and advances blocks. Once complete, the node is in dual-write mode — it will commit every new block to both timelines on next start. The monad-execution logs would print state_root primary=<slot root> secondary=<page root>, both timelines should appear for each block. Run this on every node to bring the node into dual mode. Every node must complete this phase before the MIP-8 hard fork timestamp.

Phase B - MIP-8 Hardfork

MIP-8 activation Phase B is a scheduled protocol upgrade, not an operator action. Its timestamp is encoded in a chain-wide release and is identical for every node — it only ships once the whole network has completed phase A. At that timestamp, MIP-8 activates at the execution level and the canonical state_root flips from the slot timeline to the page timeline, network-wide, in the same block:
  • Before the fork — the slot timeline is canonical; the page timeline shadows it.
  • At and after the fork — the page timeline is canonical; the slot timeline shadows it.
Which timeline is on-disk primary is independent of which one is canonical.

Phase C - Slot decommission

Historical / State Archive nodesNode storing the all state from genesis in TrieDB will keep the slot-encoded timeline active.Therefore, these node will not proceed through the Phase C, and not decommission the slot-encoded timeline.
Decommission the slot timeline Run this on each node any time after the fork.
  1. Stop the Monad services.
  2. Promote the page secondary to primary.
  3. Deactivate the now-stale slot timeline, reclaiming its disk space.
  4. Restart the Monad services. It’s now a single page timeline.
Future releases of Monad will enforce having the slot-encoded timeline decommissioned.

Further reading