> For the complete documentation index, see [llms.txt](https://docs.fast.poker/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fast.poker/for-operators-dealer-service/upgrade.md).

# Upgrade and deployment

How to upgrade, restart, and supervise the packaged Dealer Service binary.

## Built-in service manager

The packaged binary can install itself as a managed service:

```bash
./dealer service install
./dealer service status
./dealer service logs
./dealer service restart
./dealer service stop
./dealer service uninstall
```

Linux uses systemd, macOS uses launchd, and Windows uses the Service Control Manager. Add `--system` for a system-wide service or `--name <name>` for a custom service name.

The installer points the service at the binary's own folder, so `.env` and `data/` resolve beside the executable.

## Restart semantics

The dealer reads `data/crank-control.json` every 5 seconds. Two actions are recognized:

| Action                 | Exit code | Use case                                  |
| ---------------------- | --------- | ----------------------------------------- |
| `{"action":"stop"}`    | 0         | Clean shutdown, no restart expected       |
| `{"action":"restart"}` | 75        | Clean shutdown, supervisor should restart |

Exit code 75 is the conventional "EX\_TEMPFAIL" code and represents a controlled restart request.

## Upgrading the dealer binary

The dealer binary supports release checks and self-update:

```bash
./dealer update --check
./dealer update
```

The release source is the [Fast Poker dealer release repository](https://github.com/FastPoker/dealer-service/releases). Updates are verified against an Ed25519 signature baked into the binary, so an unsigned release or a checksum mismatch is refused and the running binary is left untouched. The on-chain program is upgraded separately; see the [contracts reference](/smart-contracts-reference/05-contracts.md) for the deployed program addresses.

Sequence for a clean upgrade:

1. Run `./dealer update --check`.
2. Set `crank_sng=false` and `crank_cash=false` in `data/crank-config.json` to wind down table work.
3. Wait for `tablesProcessing` to reach 0 in `data/crank-heartbeat.json`.
4. Run `./dealer update`.
5. Restart the service with `./dealer service restart`, or restart the foreground process.
6. Restore `crank_sng=true` and `crank_cash=true`.

Manual binary replacement downloads the new binary from the [release repository](https://github.com/FastPoker/dealer-service/releases) and uses the same restart sequence.

## Mixed-version safety

The dealer reads on-chain account layouts via `parsers.ts`. If the on-chain program is upgraded with a new field at a non-shadow offset, parsers must be updated. Upgrading the dealer ahead of the program upgrade is safe; upgrading the program ahead of the dealer can cause parse failures.

Coordinate upgrades with the deployed program version. Backward-compatible field additions should preserve existing account offsets so older delegated accounts can still deserialize.

The 2026-07-17 program surface requires dealer support for the 168-instruction, 36-account, 199-error public IDL and these account families: `SngDuelState`, `SngSettlementRecord`, `EmissionCtrl`, and `PoolIdle`. Do not enable SNG cranking on an older binary that omits their setup, delegation, payout, or cleanup lanes. Record-enabled tables fail closed by design.

Before restoring `crank_sng=true`, verify:

1. Global `EmissionCtrl` and all 21 `PoolIdle` accounts decode correctly.
2. Existing 6-max/9-max tables have valid 415-byte ruleset-1 sidecars.
3. The dealer can derive records by `["sng_settlement", table, start_hand]`.
4. Heartbeat/metrics recognize duel, record payout, jackpot closure, clean-table assertion, reset, and record close labels.

## Multiple dealers

Running multiple dealers is supported. Partition them deliberately:

* Run them as a fleet (shared shard map + per-instance stand-down guard) so no two instances crank the same table. See [Fleet and sharding setup](/for-operators-dealer-service/fleet-setup.md).
* Or use `table_whitelist` to give each independent dealer a disjoint set of tables.
* Confirm the sets are disjoint before starting; overlap causes `ReadonlyDataModified` and double-sent TXs.
* Coordinate restarts so the whitelist is consistent across instances.

A multi-dealer deployment is most useful for operator-license diversification (each dealer holds a different license, so weight is credited across operators).

## Rolling back

Roll back is the same as upgrading, with the previous Dealer Service binary. No on-chain state needs to be rolled back; the dealer is stateless across restarts.

## Health check after upgrade

After restart, verify:

1. Heartbeat is updating (`heartbeat` within 30s of now).
2. `tablesTracked` matches what discovery should find.
3. `data/crank-metrics.json` has a recent `updatedAt` timestamp.
4. `recentErrors` is empty or only contains expected transient errors.

If any of those fail, check the dealer log and consult [Troubleshooting](/for-operators-dealer-service/troubleshooting.md).
