Julien Divernois
02/13/2026, 7:29 AMMarvin
02/13/2026, 7:29 AMMarvin
02/13/2026, 7:34 AMJulien Divernois
02/13/2026, 7:36 AMMarvin
02/13/2026, 7:36 AMMarvin
02/13/2026, 7:42 AMdocker compose exec <your-postgres-service> pg_dump -U <db_user> <db_name> > prefect_backup_$(date +%Y%m%d_%H%M%S).sql
- Save your compose and env:
docker compose config > compose_backup_$(date +%Y%m%d_%H%M%S).yml
env > env_backup_$(date +%Y%m%d_%H%M%S).txt
3) Choose a target image tag
- For stability, pin to a specific tag (recommended): prefecthq/prefect:3.6.17
- Or track the latest patch in 3.x: prefecthq/prefect:3-latest
- Update the Prefect image tag for both the server/services and worker in your compose file.
4) Run database migrations before starting the API
- Add a one-off “migrate” service to your compose (or run it once with docker compose run):
services:
migrate:
image: prefecthq/prefect:3.6.17
depends_on:
postgres:
condition: service_healthy
environment:
PREFECT_API_DATABASE_CONNECTION_URL: postgresql+asyncpg://<user>:<pass>@postgres:5432/<db_name>
command: prefect server database upgrade -y
restart: "no"
- Important notes:
- Use the async driver in the URL: postgresql+asyncpg://...
- If you expect a large migration, you can add PREFECT_API_DATABASE_TIMEOUT="600" to allow more time.
- If you already run a separate “services” container for background jobs, set PREFECT_API_DATABASE_MIGRATE_ON_START=false on the API/services so only the migrate job performs schema upgrades.
5) Start the stack with the new image
- Stop the current stack:
docker compose down
- Pull and start:
docker compose pull
docker compose up -d migrate
docker compose logs -f migrate
- When migrate finishes successfully, bring up the API, services, and worker:
docker compose up -d prefect-server prefect-services prefect-worker
6) Verify and resume
- Check API health:
curl http://<your-host>:4200/api/health
- Open the UI and confirm it loads and shows the new version.
- Check workers reconnected and are heartbeating.
- Run a small test flow.
- Re-enable schedules.
Example compose snippets
- Server + services (core bits only; reuse your existing networking/volumes):
services:
prefect-server:
image: prefecthq/prefect:3.6.17
environment:
PREFECT_API_DATABASE_CONNECTION_URL: postgresql+asyncpg://<user>:<pass>@postgres:5432/<db_name>
# If you run a dedicated migration step:
PREFECT_API_DATABASE_MIGRATE_ON_START: "false"
command: prefect server start --host 0.0.0.0 --no-services
ports:
- "4200:4200"
depends_on:
postgres:
condition: service_healthy
prefect-services:
image: prefecthq/prefect:3.6.17
environment:
PREFECT_API_DATABASE_CONNECTION_URL: postgresql+asyncpg://<user>:<pass>@postgres:5432/<db_name>
PREFECT_API_DATABASE_MIGRATE_ON_START: "false"
command: prefect server services start
depends_on:
prefect-server:
condition: service_healthy
- Worker:
```
services:
prefect-worker:
image: prefecthq/prefect:3.6.17
environment:
PREFECT_API_URL: http://prefect-server:4200/api
command: prefect worker start --pool <your-pool-name>
depends_on:
prefect-server:Marvin
02/13/2026, 7:42 AMprefecthq/prefect container that runs the API.
Official references
- Self-hosted with Docker Compose: Docker Compose guide
- Self-hosted architecture and scaling: Self-hosted/HA guide
- Upgrading to Prefect 3.x (for context): Upgrade guide
- Latest releases: Prefect releases
Want me to review your current docker-compose.yml and suggest the exact diff (including the migrate step) for your setup? If you can share the file (with any secrets redacted), I’ll tailor the upgrade steps precisely.