ghcr.io/umami-software/umami:3.5.0@sha256:b64f4040...a5dbc in
infra/ansible/vars/pins.yml). A new version is always a deliberate change: Umami migrates its
own database (Prisma migrations) when it starts, and those migrations only go forward. So the
rollback is a database restore, never just the old image.
For a security fix inside the 24-hour target, follow security-patch.md; it
uses the same upgrade gate and adds triage and mitigations. This page is the general procedure
plus the rollback.
Upgrade
-
Gate it on the development stack (needs
make dev-up, Docker, Node 26 with pnpm and the Playwright browsers, Go 1.27.4 onPATH):scripts/umami-upgrade.shresolves the index digest the registry serves for that version, moves the pin indeploy/compose/dev.yml,infra/ansible/vars/pins.yml,tests/observability/compose.ymlanddocs/reference/umami-contract.md, recreates the dev stack so Umami migrates the existing database, then runsumami-compat, the isolation gate,console-e2eandwebpath, stopping at the first failure. Each step printsstep <name>: ok in <n> s. A new version stays red atumami-compatuntil someone has reviewed its OpenAPI routes against the Caddy deny list and updatedtests/umami-compat/testdata/openapi-routes.txt. Commit the diff only when every gate passed. -
Release. Merge, tag
v<release>;release-images.ymlbuilds, scans and signs the platform images and attachesrelease-images.json. Umami itself is an upstream image and is pulled by its pinned digest. -
Take a dump of the Umami database before the rollout. On the core node that holds the
Patroni leader (overview.md):
Write down the time and the migration line (for 3.5.0:
27 migrations, last 27_add_error_tracking). The point-in-time backups also cover this moment, but a dump of one database is far quicker to restore. -
Roll out to staging, then production:
deploy.ymldrains and updates one node at a time and stops at the first unhealthy node. The new Umami migrates the database on its first start on the first core node. -
Verify: ../deploy/verification.md steps for the core tier,
UmamiHeartbeatFailingstays quiet, a tenant dashboard opens through the console’s SSO, andWEB_EVENTSdrains (queue-backlog-and-dlq.md).
Rollback
Use it when the new version misbehaves in a way a fix-forward cannot address in time.-
Stop delivery into Umami on both core nodes, so nothing more is written to the database
you are about to replace. Accepted events wait in
WEB_EVENTS(72 hours):Run it on both core nodes. The list names every Umami process:umamiplusumami-2up toumami-<core_umami_processes>(4 by default;sudo docker compose psshows them). Tenant web dashboards are down from here until step 5. -
Restore the dump on the leader’s node:
Then recreate the retention role’s grants, which live in the Umami database: run
platformctl db umami-retention-roleas in overview.md. -
Check the migration level matches what step 3 of the upgrade recorded:
-
Deploy the previous release, whose
pins.ymlnames the previous Umami digest. In your working copy check out that release’s tag, then:The deploy starts Umami and the replayer again. - Verify as in upgrade step 5. The replayer delivers what queued since step 1.
WEB_EVENTS, so nothing re-sends
them. Keep the time between the dump and the decision short, and tell the tenants which window
is affected. The platform database (control plane, API metrics) is not touched by this rollback.
Exercised
Not yet exercised: the rollout and rollback through
deploy.yml on staging (inputs I4, I5,
I6, I13, I14, I15), the dump on a Patroni leader, and the retention role step after a restore.
The phase 19 rehearsal used plain containers with the same images and the same pg_dump and
pg_restore commands.