CapyDB/ docs
Guides

Version upgrades

How PostgreSQL minor and major upgrades work on CapyDB - what is automatic, what you control, and what we apply on your behalf.

PostgreSQL versions move in two very different ways, and CapyDB treats them differently because the risk is not comparable.

Minor (17.4 → 17.5)Major (17 → 18)
On-disk formatIdenticalChanges
What it takesA restartA migration
Write interruptionSecondsFull copy and verification window
Who starts itMostly automaticYou check; CapyDB executes
ReversibleNothing to reverseYes, with post-cutover writes discarded

Minor upgrades

Minor releases are binary-compatible. Your data is not touched, nothing is rewritten, and no migration runs - the new version is simply a different server binary reading the same files. Security fixes ship as minors, so this is the path that matters most.

If your database uses scale-to-zero, it upgrades itself. A paused database starts on whatever version is current when it next resumes, so most cells pick up a minor with no action and no interruption at all.

A database that is running when a minor lands keeps its current version until it restarts. The dashboard reports this, and you can apply it whenever suits you:

POST /v1/projects/{projectID}/upgrade/minor

The restart interrupts open connections briefly - that is the entire cost, and it is why we do not do it silently underneath you. The platform refuses to restart while queries are actually running, so a busy database is skipped rather than disrupted.

When we apply one on your behalf

For an urgent security release, CapyDB will apply a minor upgrade fleet-wide after a stated deadline, whether or not it has been applied by then. You are told in advance and can apply it earlier at a time you choose; the deadline exists so an unpatched database cannot sit exposed indefinitely. This is the one case where the timing is not entirely yours.

Major upgrades

Major upgrades change the on-disk format, so they are a real migration and never happen without you: you run the readiness check yourself, and the migration itself is performed with CapyDB when you are ready.

Check first

A major upgrade can fail after it starts building the replacement, so known blockers are checked up front:

POST /v1/projects/{projectID}/upgrade/major/preflight?target_major=18

The result is upgradable or blocked, with specific reasons. The blocker that matters most in practice is extensions: if something you use has no build for the target major, migrating would leave your schema referencing types and functions that no longer exist. Better to know before than after.

The check changes nothing and can be re-run as often as you like.

How the migration runs

CapyDB does not upgrade your database in place. It builds a new database on the target version. Immediately before the logical copy begins, the original is made read-only and existing client sessions are disconnected. It stays read-only while CapyDB copies and verifies the data, then your project is pointed at the verified replacement. Plan a maintenance window that covers the full copy and verification, not only the final switch.

The frozen original is retained until you confirm the upgrade or the retention window expires. Rollback points the project back at that copy, so every write accepted by the upgraded database after cutover is discarded. Stop writers before requesting rollback and preserve any post-cutover data you need separately. Confirmation destroys the retained copy and permanently removes this rollback path.

Your connection string does not change.

What travels with your data

The copy carries your planner statistics, not just your rows. A restored database with no statistics plans badly until something analyses it - which on a database that spends most of its time paused can be a long wait - so the upgrade analyses the replacement before the cutover rather than leaving the first queries to pay for it.

Schemas move across majors as written. That is why a column default calling a function whose name differs between majors is the one thing most likely to bite you here - see Postgres 18 features for the portable spelling.

Extensions

Extensions version independently of PostgreSQL. When a newer build of one you use becomes available, the dashboard offers an Update action on the Extensions page:

POST /v1/projects/{projectID}/extensions/{name}/update

This is yours to trigger, not something applied automatically, because an extension's upgrade scripts can change behaviour inside your data - a PostGIS upgrade may require reindexing afterwards, for example. Extensions CapyDB installs for its own observability are kept current automatically and are never offered here.

Applying an update when the extension is already current is a no-op, so it is safe to retry.