# Examples

> End-to-end Mesa upgrade walkthroughs by role and deployment style — block producer (automode/manual), archive node, zkApp developer, and exchange.

Canonical URL: https://docs.minaprotocol.com/network-upgrades/mesa/upgrade-steps/examples

The walkthroughs below follow concrete operators through the four Mesa upgrade phases (Pre-Upgrade, [State Finalization](/network-upgrades/mesa/upgrade-steps/state-finalization), [Upgrade](/network-upgrades/mesa/upgrade-steps/upgrade), [Post-Upgrade](/network-upgrades/mesa/upgrade-steps/post-upgrade)) for different roles and setups. Click to expand the example that matches your situation.

<details>
<summary><b>Example: Block Producer Upgrading with Automode (Debian)</b></summary>

Imagine you are **Alice**, a block producer running on a Debian server. Here is what your upgrade looks like end to end.

**Weeks before the fork** — Alice checks [hardware requirements](/network-upgrades/mesa/requirements) and installs the automode packages:

```bash
sudo apt-get update
sudo apt-get install mina-mainnet-automode=4.x.x
```

She starts her node normally. The dispatcher (installed as `/usr/local/bin/mina`) needs one automode-specific setting: **`MINA_HARDFORK_STATE_DIR` must point at her config directory** — it must match `--config-directory`, because that is where the dispatcher looks for the `auto-fork-mesa-mainnet/activated` marker to choose between the pre-fork and Mesa runtime. Export the variable and pass the matching flag:

```bash
export MINA_HARDFORK_STATE_DIR=~/.mina-config

mina daemon \
  --block-producer-key ~/keys/my-wallet \
  --config-directory ~/.mina-config \
  --libp2p-keypair ~/keys/libp2p-key \
  --peer-list-url https://bootnodes.minaprotocol.com/networks/mainnet.txt \
  --file-log-rotations 500 \
  --log-json
```

The automode dispatcher runs the pre-fork binary until the fork activates. To preview which runtime and arguments the dispatcher will exec without running it, prefix the command with `MINA_DISPATCHER_DRYRUN=1`.

> For the full preparation checklist, see [Requirements](/network-upgrades/mesa/requirements).

**Hours before the fork (State Finalization)** — The network reaches the _stop-transaction-slot_. Alice's node keeps producing blocks — she does **nothing**. Empty blocks are produced for 100 slots (exactly 5 hours) until all nodes agree on the final state.

> For details on this phase, see [State Finalization](/network-upgrades/mesa/upgrade-steps/state-finalization).

**Fork day (Upgrade)** — The network halts at the _stop-network-slot_. Alice's daemon generates the Mesa configuration, writes the `activated` marker file, and **shuts down cleanly** (exit code 0). Because Alice uses systemd with `Restart=always`, the daemon restarts automatically. On restart, the dispatcher detects the `activated` file and launches the Mesa binary. Alice does **nothing** — this all happens automatically.

> For what happens if you chose manual mode instead, see [Upgrade](/network-upgrades/mesa/upgrade-steps/upgrade). For details on the restart mechanism, see [Upgrade Modes - Details](/network-upgrades/mesa/appendix/upgrade-modes-details#restart-and-filesystem-requirements).

**After the fork (Post-Upgrade)** — Exactly 3 hours after the _stop-network-slot_, the first Mesa block is produced. Alice verifies:

```bash
# Check if the activated file exists (path depends on your config directory and network ID)
ls ~/.mina-config/auto-fork-mesa-mainnet/activated

# Confirm Mesa chain ID
mina client status
```

:::note Dispatcher and non-daemon commands
The automode dispatcher only supports `daemon` and `client status` subcommands. For other commands, invoke the version-specific binary by its full path (`/usr/lib/mina/mesa/mina` or `/usr/lib/mina/berkeley/mina`) directly. See [Troubleshooting](/network-upgrades/mesa/troubleshooting#can-i-run-non-daemon-commands-or-use-a-specific-binary-version) for details.
:::

She's done. Her node is producing blocks on Mesa.

> For post-upgrade verification, monitoring, and flag reference, see [Post-Upgrade](/network-upgrades/mesa/upgrade-steps/post-upgrade#flag-and-configuration-reference).

</details>

<details>
<summary><b>Example: Block Producer — Manual Mode (Docker)</b></summary>

**Carlos** runs a block producer using Docker and prefers manual control over the upgrade.

**Weeks before the fork** — Carlos pulls the stop-slot Docker image and starts his node:

```bash
docker pull minaprotocol/mina-daemon:<version>-bullseye-mainnet

docker run --name mina -d \
  --restart=always \
  -v mina-config:/root/.mina-config \
  minaprotocol/mina-daemon:<version>-bullseye-mainnet \
  daemon \
    --block-producer-key /keys/my-wallet \
    --config-directory /root/.mina-config \
    --libp2p-keypair /keys/libp2p-key \
    --peer-list-url https://bootnodes.minaprotocol.com/networks/mainnet.txt \
    --file-log-rotations 500 \
    --log-json
```

> For the full preparation checklist, see [Requirements](/network-upgrades/mesa/requirements).

**Hours before the fork (State Finalization)** — Carlos keeps his node running. He does **nothing** during this phase.

> For details on this phase, see [State Finalization](/network-upgrades/mesa/upgrade-steps/state-finalization).

**Fork day (Upgrade)** — The network halts at the _stop-network-slot_. Carlos waits for the Mesa release announcement, then swaps to the new image.

> Throughout these examples, `<mesa-version>` is a placeholder for the Mesa release tag announced for your target network. For the **Mesa Trail** test network the current value is published on [Mesa Trail Network](/network-upgrades/mesa/mesa-trail); for **devnet/mainnet** the value will be published with the corresponding release announcement.

```bash
docker stop mina && docker rm mina

docker pull minaprotocol/mina-daemon:4.0.0-6850301-bullseye-mainnet

docker run --name mina -d \
  --restart=always \
  -v mina-config:/root/.mina-config \
  minaprotocol/mina-daemon:4.0.0-6850301-bullseye-mainnet \
  daemon \
    --block-producer-key /keys/my-wallet \
    --config-directory /root/.mina-config \
    --libp2p-keypair /keys/libp2p-key \
    --peer-list-url https://bootnodes.minaprotocol.com/networks/mainnet.txt \
    --file-log-rotations 500 \
    --log-json
```

> For detailed upgrade instructions, see [Upgrade](/network-upgrades/mesa/upgrade-steps/upgrade).

**After the fork (Post-Upgrade)** — Exactly 3 hours after the _stop-network-slot_, block production starts. Carlos verifies:

```bash
docker exec mina mina client status   # confirms Mesa chain ID
```

> For post-upgrade verification, monitoring, and flag reference, see [Post-Upgrade](/network-upgrades/mesa/upgrade-steps/post-upgrade#flag-and-configuration-reference).

</details>

<details>
<summary><b>Example: Archive Node / Explorer Operator</b></summary>

**Eve** runs an archive node, a Rosetta API instance, and a block explorer. She needs to upgrade both the daemon and the database.

**Weeks before the fork** — Eve installs the stop-slot release and decides on her upgrade method:

```bash
sudo apt-get update
sudo apt-get install mina-mainnet=3.x.x
```

She chooses the **trustless** path — running the upgrade script early, while her archive is still online:

```bash
# Install the Mesa archive package — it ships the upgrade script at
# /etc/mina/archive/upgrade_to_mesa.sql. The upgrade is backward-compatible,
# so her Berkeley archive keeps running normally afterwards.
sudo apt-get update
sudo apt-get install mina-archive-mainnet=4.0.0-6850301

# Back up the database first
pg_dump -U <user> archive_db > berkeley-archive-backup.sql

# Run the shipped upgrade script (completes in under 1 minute)
psql -U <user> -d archive_db -f /etc/mina/archive/upgrade_to_mesa.sql

# Verify
psql -U <user> -d archive_db -c "SELECT * FROM migration_history;"
```

The script is backward-compatible — her existing Berkeley archive node keeps working normally after the upgrade.

> For the full archive upgrade guide, see [Archive Upgrade](/network-upgrades/mesa/archive-upgrade).

**Hours before the fork (State Finalization)** — Eve keeps her archive node running to capture all finalized blocks.

> For details on this phase, see [State Finalization](/network-upgrades/mesa/upgrade-steps/state-finalization).

**Fork day (Upgrade)** — The network halts. Eve installs the Mesa archive release and points it at her already-upgraded database:

```bash
sudo systemctl stop mina-archive
sudo systemctl stop mina

sudo apt-get update
sudo apt-get install mina-archive-mainnet=4.0.0-6850301 mina-mainnet=4.0.0-6850301

# Start archive process pointing to the upgraded DB
mina-archive run \
  --postgres-uri postgres://<user>:<pass>@localhost:5432/archive_db \
  --server-port 3086 \
  --log-json --log-level DEBUG

# Start the non-block-producing daemon connected to the archive
mina daemon \
  --archive-address localhost:3086 \
  --config-directory ~/.mina-config \
  --libp2p-keypair ~/keys/libp2p-key \
  --peer-list-url https://bootnodes.minaprotocol.com/networks/mainnet.txt \
  --file-log-rotations 500 \
  --log-json
```

She also restarts Rosetta:

```bash
docker run --name rosetta --rm -d \
  -p 3088:3088 \
  --entrypoint '' \
  minaprotocol/mina-rosetta:4.0.0-6850301-bullseye-mainnet \
  /usr/local/bin/mina-rosetta \
    --archive-uri "postgres://<user>:<pass>@localhost:5432/archive_db" \
    --graphql-uri "http://localhost:3085/graphql" \
    --log-json --port 3088
```

> For detailed upgrade instructions, see [Upgrade](/network-upgrades/mesa/upgrade-steps/upgrade).

**After the fork (Post-Upgrade)** — Block production resumes. Eve verifies data integrity:

```bash
# Check the archive is in sync
mina client status

# Run the verification toolbox
mina-archive-hardfork-toolbox verify-upgrade \
  --postgres-uri postgres://<user>:<pass>@localhost:5432/archive_db \
  --protocol-version <version> \
  --migration-version <version>
```

She checks her explorer UI to confirm new Mesa blocks are appearing and the historical data is intact.

> For the full validation workflow, see [Post-Upgrade](/network-upgrades/mesa/upgrade-steps/post-upgrade) and the [Archive Hardfork Toolbox](/network-upgrades/mesa/archive-upgrade#verification-with-the-archive-hardfork-toolbox).

</details>

<details>
<summary><b>Example: zkApp Developer</b></summary>

**Frank** maintains a zkApp deployed on mainnet. His contract uses on-chain state and he wants to take advantage of Mesa's expanded 32-field state.

**Weeks before the fork** — Frank updates his o1js dependency to the Mesa-compatible version and tests his zkApp on the [Mesa Trail test network](/network-upgrades/mesa/mesa-trail):

```bash
npm install o1js@3.0.0-mesa.rc2
```

This release targets the Mesa transaction protocol. `o1js@latest` currently resolves to a pre-Mesa version and will produce transactions that Mesa nodes reject. See [Mesa Trail Network](/network-upgrades/mesa/mesa-trail) for the matching daemon/archive/rosetta release.

He verifies that:
- His contract recompiles cleanly against Mesa-compatible o1js and deploys on Mesa Trail
- Transactions execute end-to-end against the redeployed contract
- If he plans to use the expanded state fields (indexes `8–31`), his updated contract version compiles and deploys on Mesa Trail

> For details on testing against Mesa Trail, see [Mesa Trail Network](/network-upgrades/mesa/mesa-trail).

**Hours before the fork (State Finalization)** — Frank does **nothing**. His deployed zkApp keeps running on the Berkeley chain. No transactions can be submitted during this phase anyway.

**Fork day (Upgrade)** — Frank does **nothing during the network halt**. His zkApp account and on-chain state values carry over to the Mesa chain automatically (including state fields at indexes `0–7`). However, the verification key generated for Berkeley is no longer valid under the Mesa protocol — the contract cannot process transactions on Mesa until it is redeployed.

**After the fork (Post-Upgrade)** — Block production resumes on Mesa. Frank **must redeploy his zkApp** before it can accept transactions, regardless of whether he uses the new state fields:

```bash
# Required for every zkApp — the Mesa protocol version bump invalidates the Berkeley verification key
zkapp deploy --network mainnet
```

If he is also adopting the expanded `8–31` state slots, this same deployment step ships the updated contract version that declares the new fields.

> For post-upgrade details, see [Post-Upgrade](/network-upgrades/mesa/upgrade-steps/post-upgrade).

</details>

<details>
<summary><b>Example: Exchange Upgrading to Mesa</b></summary>

**Bob** is an exchange operator. His main concern is avoiding lost deposits.

Bob runs the full Rosetta-based stack, so he upgrades **three packages** — the node, the archive node, and the Rosetta API — plus his PostgreSQL archive database:

- `mina-mainnet` — the daemon
- `mina-archive-mainnet` — the archive node
- `mina-rosetta-mainnet` — the Rosetta API

(Exchanges on a custom GraphQL integration that do not run Rosetta or an archive only need `mina-mainnet`.)

**Weeks before the fork** — Bob tests his integration (Rosetta API, mina-signer) on the [Mesa Trail test network](/network-upgrades/mesa/mesa-trail). He reviews [schema changes](/network-upgrades/mesa/appendix/archive-node-schema-changes) and installs the stop-slot release on his node:

```bash
sudo apt-get install mina-mainnet=3.x.x
```

> For the full exchange preparation checklist, see [Requirements](/network-upgrades/mesa/requirements).

**Hours before the fork** — Before the _stop-transaction-slot_ arrives, Bob **disables MINA deposits and withdrawals** on his platform and notifies customers about the maintenance window.

:::danger
Any transactions submitted after the stop-transaction-slot **will not exist on the Mesa chain**. See [State Finalization](/network-upgrades/mesa/upgrade-steps/state-finalization#exchanges) for the full exchange guidance.
:::

**Fork day** — The network halts. Bob waits for the Mesa release announcement, then upgrades all three components and migrates his archive database:

```bash
# Stop the stack
sudo systemctl stop mina mina-archive

# Install the Mesa releases for the node, archive, and Rosetta
sudo apt-get update
sudo apt-get install mina-mainnet=4.0.0-6850301 mina-archive-mainnet=4.0.0-6850301 mina-rosetta-mainnet=4.0.0-6850301

# Upgrade the archive schema — the mina-archive package ships the script
psql -U <user> -d archive_db -f /etc/mina/archive/upgrade_to_mesa.sql

# Restart the node and archive, then bring Rosetta back up
sudo systemctl start mina mina-archive
```

> For detailed upgrade instructions, see [Upgrade](/network-upgrades/mesa/upgrade-steps/upgrade).

**After the fork** — Block production resumes. Bob verifies his node is on the Mesa chain, confirms Rosetta API is working, then **re-enables MINA deposits and withdrawals**.

```bash
mina client status   # verify Mesa chain ID
# test a small internal transfer before opening to customers
```

> For post-upgrade verification, monitoring, and flag reference, see [Post-Upgrade](/network-upgrades/mesa/upgrade-steps/post-upgrade#flag-and-configuration-reference).

</details>
