DocumentationChangelog
Administration

Upgrades & rollback

Promotion is one line: change the pinned tag and bring the service back up. Rolling forward is safe; rolling back has one trap, and it is worth knowing before you need to know it.

Promoting a version

Always take a backup first. Then move the pin and pull:

terminal
cd ~/control
sed -i 's/^TALON_CONTROL_IMAGE_TAG=.*/TALON_CONTROL_IMAGE_TAG=sha-<new>/' .env
docker compose pull app
docker compose up -d app

Migrations apply at boot, before the server accepts a request. There is no separate migration step to remember and no window where new code runs against an old schema.

Never pin a floating tag
A tag that moves makes "what is running right now" unanswerable, and turns rollback from a decision into a guess. Pin the exact build; promoting is then a deliberate act with a diff behind it.

What survives

The database volume
Everything the company is. Nothing about an upgrade touches it beyond applying migrations.
The data volume
App Logs history and dev-session git checkouts and engine state.
The model cache
The local speech models. Losing it costs a re-download and a temporarily different voice, nothing more.
Never put -v in a deploy script
docker compose down keeps all three volumes. down -v deletes them — including the database. There is no confirmation prompt and no undo.

Rollback, and the trap in it

Putting the previous tag back and bringing the service up rolls the image back. It does not roll the schema back — migrations applied at boot and nothing reverses them.

Additive migrations — new tables, new nullable columns — are safe to roll back under. Old code simply does not know the new column exists.
Destructive migrations — a drop, a rename, a narrowed type — are not. Old code will query something that is no longer there.
The honest recovery for the second case is restore the dump, then run the old image. Which is only possible if you took the dump first.

Release notes say which kind a build contains. Read that line before promoting, not after.

Verifying the upgrade

terminal
docker compose ps # healthy
docker compose images app # the tag you expect
curl -s localhost:3001/api/health/ready # {"status":"ready"}

/api/health/ready checks Postgres too, so a healthy answer means "can serve" rather than merely "process alive". A 503 is the app up and the database unreachable — look at the database container first, every time.