Upgrading
An upgrade replaces the binary or image and applies any new database migrations. Migrations are embedded in the binary and forward-only: there is no down migration, so the way back is a restore, which is why every upgrade starts with a backup.
Before you start
Read the notes for every version between yours and the target (per-version notes).
Take a database dump and confirm it finished. Keep
ENCRYPTION_KEYandJWT_SECRETunchanged; see Backup and restore.shpg_dump --format=custom --file="sphericon-pre-upgrade.dump" \ "postgres://backup_user@db.example.com:5432/sphericon?sslmode=require"Note the version you are running (
./sphericon version, or the image tag), so you can go back.
Upgrade
Single replica. Replace the image or binary and restart. With AUTO_MIGRATE=true the process applies pending migrations on startup.
Multiple replicas. Do not use AUTO_MIGRATE: replicas would race. Run the migration once, then roll the servers.
Run the new version's migration step against the production database. It applies pending migrations and exits:
shdocker run --rm \ -e APP_ENV=production \ -e DATABASE_URL="postgres://app@db.example.com:5432/sphericon?sslmode=require" \ -e JWT_SECRET="$JWT_SECRET" \ ghcr.io/mokevnin/sphericon:<new-version> migrateFor the plain binary run
./sphericon migratewith the same environment. Use it as a pre-deploy job or an init container. It applies the application migrations and river's own job-queue schema.On Kubernetes use the in-repo Helm chart (
charts/sphericon): it runsmigrateas a pre-install/pre-upgrade hook Job, so the Deployment only rolls after it succeeds. Create a Secret withDATABASE_URL,JWT_SECRETandENCRYPTION_KEYfirst and pass its name asexistingSecret(the chart refuses to render without it). Metrics stay off unless you setmetrics.enabled;metrics.serviceMonitor.enabledadds a Prometheus Operator ServiceMonitor that scrapes the internal listener only.Roll the replicas to the new version one at a time, waiting for
GET /readyzto return200on each before moving on.
Pin the image to an explicit version tag in production instead of latest, so a restart never upgrades you by accident.
Roll back
Migrations only go forward, so a rollback means returning to the pre-upgrade state:
- Stop every replica.
- Restore the pre-upgrade dump into an empty database (see the restore drill) and point
DATABASE_URLat it, or drop and recreate the database you are restoring over. - Start the previous image or binary.
Anything written after the dump is lost, and the points in After a restore apply. If the upgrade is only minutes old, weigh whether fixing forward is cheaper than losing that window.
Per-version notes
sphericon is versioned with release-please from Conventional Commits. The authoritative list of changes for each release is the GitHub releases page. The table below records only what needs an operator's attention beyond "run migrate": a new required setting, a removed one, a slow migration, a changed default.
| Version | Operator action |
|---|---|
| 0.x | Pre-release series. No special steps are recorded beyond running migrate. |
Read any row added here before you upgrade past that version.
PostgreSQL major upgrades
A PostgreSQL major upgrade (for example 16 to 17) is a database administration task, independent of sphericon releases. Do not combine it with an application upgrade: change one thing at a time, so a failure has one suspect.
- Check that the target major version is supported (see Self-hosting for the supported range).
- Take a fresh dump and rehearse the whole procedure on a scratch copy first.
- Upgrade in place with
pg_upgrade, or dump from the old server and restore into a new server on the new major version (pg_dumpthenpg_restore). Managed services offer their own major-version upgrade. - Stop sphericon during the switch, repoint
DATABASE_URLif the server changed, start it, and checkGET /readyz. - Run
ANALYZEon the new cluster: planner statistics are not always carried over.
A physical backup or WAL archive from the old major version cannot be restored onto the new one. Take a fresh base backup right after the upgrade, and keep the pre-upgrade pg_dump until you are confident in the new cluster.