Versions & Upgrades
When you deploy new code, Rivet ensures actors are upgraded seamlessly without downtime.
How Versions Work
Each runner has a version number. When you deploy new code with a new version, Rivet handles the transition automatically:
- New actors go to the newest version: When allocating actors, Rivet always prefers runners with the highest version number
- Multiple versions can coexist: Old actors continue running on old versions while new actors are created on the new version
- Drain old actors: When enabled, a runner connecting with a newer version number will gracefully stop old actors to be rescheduled to the new version
Versions are not configured by default. See Registry Configuration to learn how to configure the runner version.
Example Scenario
When a new version is deployed, existing actors are immediately drained from the old runner and live migrated to the new version.
When a new version is deployed, both versions coexist. New actors are created on the new version while existing actors continue running on the old version until.
Configuration
Setting the Version
Configure the runner version using an environment variable or programmatically:
RIVET_RUNNER_VERSION=2
import { actor, setup } from "rivetkit";
const myActor = actor({ state: {}, actions: {} });
const registry = setup({
use: { myActor },
runner: {
version: 2,
},
});
We recommend injecting a value at built time that increments every deployment, such as:
- Build timestamp
- Git commit number (
git rev-list --count HEAD) - CI build number (
github.run_number)
Drain on Version Upgrade
The drainOnVersionUpgrade option controls whether old actors are stopped when a new version is deployed. This is configured in the Rivet dashboard under your runner configuration.
| Value | Behavior |
|---|---|
false (default in runner mode) | Old actors continue running. New actors go to new version. Versions coexist. |
true (default in serverless mode) | Old actors receive stop signal and have 30s to finish gracefully. |
Advanced
How Version Upgrade Detection Works
When drainOnVersionUpgrade is enabled, Rivet uses two mechanisms to detect version changes:
- New runner connection: When a runner connects with a newer version number, the engine immediately drains all older runners with the same name. This is the primary mechanism for runner mode deployments.
- Metadata polling (serverless only): In serverless mode, runners periodically poll the engine to check for newer versions and self-drain if one is found. This ensures old runners drain even if no new requests trigger a runner connection.
SIGTERM Handling
When a runner process receives SIGTERM, it gracefully stops all actors before exiting:
- Each actor’s
onSleephook is called, giving it time to save state - Actors are rescheduled to other available runners
- The runner waits up to 120 seconds for all actors to finish stopping
- If the process is force-killed before actors finish (e.g. SIGKILL), actors are rescheduled with a crash backoff penalty instead of a clean handoff
Ensure your platform’s shutdown grace period is at least 130 seconds to give actors time to stop cleanly.
Shutdown Timeouts
Several timeouts control how long each part of the shutdown process can take:
| Timeout | Default | Description | Configuration |
|---|---|---|---|
actor_stop_threshold | 30s | Engine-side limit on how long each actor has to stop before being marked lost | Engine config (pegboard.actor_stop_threshold) |
onSleepTimeout | 5s | How long the onSleep hook can run | Actor options |
runStopTimeout | 15s | How long to wait for the run handler to exit | Actor options |
waitUntilTimeout | 15s | How long to wait for background waitUntil promises to resolve | Actor options |
runner_lost_threshold | 15s | Fallback detection if the runner dies without graceful shutdown | Engine config (pegboard.runner_lost_threshold) |
The per-actor timeouts (onSleepTimeout, runStopTimeout, waitUntilTimeout) must fit within actor_stop_threshold. The runner’s 120-second wait is a hard upper bound on the entire shutdown process.
Related
- Runtime Modes: Serverless vs runner deployment modes
- Lifecycle: Actor lifecycle hooks including
onSleep