Coolify logoCoolify

Internal PostgreSQL upgrade

Coolify self-hosted instances use an internal PostgreSQL database container named coolify-db. Normal Coolify updates do not automatically upgrade PostgreSQL to a new major version.

PostgreSQL major upgrades, for example 15 to 18, require a data migration. Changing only the Docker image is not enough, because PostgreSQL will reject data directories created by a different major version.

Backup first

Create or verify a recent Coolify backup before upgrading the internal PostgreSQL database. The upgrade script keeps the previous Docker volume for rollback, but you should still have an external backup before changing database versions.

When to use this

Use this only when you need to upgrade the internal Coolify database to a newer PostgreSQL major version.

Do not use this for PostgreSQL databases that you created as project resources in Coolify. Those databases have their own lifecycle and backup/restore process.

Upgrade PostgreSQL

Run the script on your Coolify server:

/data/coolify/source/upgrade-postgres.sh 18

Replace 18 with the target PostgreSQL major version.

The script will:

  1. Detect the current coolify-db PostgreSQL version.
  2. Stop the coolify application container to prevent writes.
  3. Create a compressed pg_dumpall backup in /data/coolify/backups/internal-postgres/.
  4. Create a new Docker volume, for example coolify-db-pg18.
  5. Restore the dump into a temporary PostgreSQL container using the target version.
  6. Smoke-test the restored database.
  7. Write /data/coolify/source/docker-compose.postgres-upgrade.yml.
  8. Restart the Coolify stack using the new PostgreSQL image and volume.
  9. Save rollback metadata in /data/coolify/source/postgres-upgrade-rollback.env.

PostgreSQL 18 volume path

PostgreSQL 18 and newer use /var/lib/postgresql as the container mount path. Older versions use /var/lib/postgresql/data. The script chooses the correct path automatically.

What changes in Docker Compose

The script does not modify docker-compose.yml or docker-compose.prod.yml. Instead, it creates this override file:

/data/coolify/source/docker-compose.postgres-upgrade.yml

For PostgreSQL 18, it looks similar to this:

services:
  postgres:
    image: "postgres:18-alpine"
    volumes:
      - coolify-db:/var/lib/postgresql
volumes:
  coolify-db:
    name: "coolify-db-pg18"
    external: true

Future Coolify updates include this override file automatically, so the upgraded image and volume stay active after normal upgrades.

If you also have /data/coolify/source/docker-compose.custom.yml, the PostgreSQL upgrade override is loaded after the custom compose file. For conflicting postgres service settings, the PostgreSQL upgrade override takes precedence.

Roll back

If the upgraded database does not work, run:

/data/coolify/source/upgrade-postgres.sh rollback

Rollback uses the metadata saved during the last successful upgrade. It restores the previously active PostgreSQL image, Docker volume, and mount path.

For example:

15 → 18 → rollback = 15
15 → 18 → 19 → rollback = 18

Rollback is one-step only. Each successful upgrade replaces the rollback metadata with the previously active version.

The upgraded Docker volume is not deleted during rollback. You can inspect or remove it manually after you confirm the rollback works.

Files created by the script

FilePurpose
/data/coolify/source/docker-compose.postgres-upgrade.ymlCompose override that points Coolify to the upgraded PostgreSQL image and Docker volume.
/data/coolify/source/postgres-upgrade-rollback.envMetadata used by upgrade-postgres.sh rollback.
/data/coolify/source/postgres-upgrade-*.logUpgrade or rollback logs.
/data/coolify/backups/internal-postgres/postgres-upgrade-*.sql.gzCompressed database dump created before migration.

Verify the active compose configuration

To inspect the final Compose configuration that will be used by Coolify, run:

docker compose \
  --env-file /data/coolify/source/.env \
  -f /data/coolify/source/docker-compose.yml \
  -f /data/coolify/source/docker-compose.prod.yml \
  -f /data/coolify/source/docker-compose.custom.yml \
  -f /data/coolify/source/docker-compose.postgres-upgrade.yml \
  config

If you do not have docker-compose.custom.yml, remove that line from the command.

On this page