2026.09 / release recovery 060
Coolify rollback after a failed deploy: protect database state
A Coolify deployment reaches production, a critical user flow breaks, and the previous release worked. Selecting an older image can restore the application code quickly—but it does not put the whole system back in time.
Coolify’s rollback documentation is explicit: rollback deploys an older application image retained on the server. It does not reverse database migrations, restore persistent storage, or undo changes to external services. The old image also starts with the application’s current runtime configuration. That distinction turns “click rollback” into a compatibility decision.
A Coolify rollback changes the application image. Treat the database, volumes, environment variables, queues, object storage, caches, and third-party APIs as separate state.
First decide whether rollback is the right response
Rollback is a good candidate when the failing behaviour lives in application code or image contents and the previous image remains compatible with current state. Examples include a broken route, a frontend regression, an incorrect dependency, or a process that will not start.
A forward fix may be safer when the release has already made an irreversible or incompatible state change. Before touching the rollback control, answer these questions:
- Did the release run a database migration? Was it additive, destructive, or data-transforming?
- Did it change a persisted file format, volume layout, cache schema, queue payload, or object-storage key?
- Did current environment variables, secrets, mounts, domains, ports, or feature flags change?
- Are workers from both versions processing the same queue?
- Can the old code read and write the schema that exists now?
If you cannot establish compatibility and the service handles important writes, pause or drain those writes before experimenting. Preserving evidence and preventing new inconsistent data is more useful than making the homepage green while background jobs keep corrupting state.
1. Capture the failed release before changing it
Record the deployment identifier, expected Git commit, failure time, affected user flow, current application logs, migration output, and the image you intend to restore. Do not put tokens, passwords, private connection strings, or real origin addresses in the incident notes.
Use the Coolify deployment screen for the exact operation. On a host where you are authorised to inspect Docker, read-only commands can help correlate containers and images:
docker ps --no-trunc \
--format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
docker inspect APP_CONTAINER \
--format '{{.Config.Image}} {{.Image}} {{json .State.Health}}'
docker logs --since 20m APP_CONTAINER
Redact output before sharing it: environment values and labels can expose credentials or infrastructure details. The goal is a release fingerprint and failure class, not a public dump of the container configuration.
2. Confirm that Coolify still has the previous image
Open the application’s Configuration → Rollback view and identify the previous working image. Coolify can only offer images it still retains locally. Its documentation notes that application image-retention settings can be overridden at server level, and an image removed by cleanup no longer appears as a rollback target.
Do not compensate by guessing a mutable tag such as latest. A tag can point somewhere different from the release you remember. Prefer the exact retained Coolify entry or an immutable image digest from a trusted registry and deployment record.
If the target is absent, rebuilding an old commit is a new deployment, not the same operation as restoring the original image. Dependencies and base images may have moved. Reproduce and test that build before calling it a rollback.
3. Classify the database migration
The hardest rollback failures happen when old code meets a new schema. Classify each migration that ran:
- Additive: a nullable column, new table, or new index. Old code often tolerates this, but triggers and constraints still need review.
- Contracting: dropping or renaming a column, table, enum value, or index expected by old code. Rolling the image back can immediately fail.
- Semantic: values were converted, split, merged, re-encrypted, or assigned new meaning. The old code may run while silently interpreting them incorrectly.
- Operational: a large backfill or index build is still running. Starting the old app can create load or conflicting writes.
An application rollback should not automatically run a “down” migration. Destructive down migrations can lose data written since the deploy, and many production migrations are not truly reversible. Take a fresh backup or storage snapshot according to the database’s documented method before any state-changing recovery. Then choose deliberately among three paths:
- Roll back only the image because the new schema is backward compatible.
- Ship a forward compatibility fix that makes the current release safe.
- Restore database state through the tested database recovery plan, accepting and accounting for the recovery point—not through the application rollback button.
For future releases, the expand-and-contract pattern reduces this risk: add the new shape first, deploy code that can handle both shapes, migrate data, stop old writes, and remove the old shape in a later release.
4. Compare current runtime settings with the old image
Coolify states that the selected older image uses the current runtime configuration. Review environment-variable names and build/runtime scope, mounted paths, exposed ports, health-check path, command overrides, domains, and network dependencies before starting it.
This matters when a release replaced OLD_API_URL with NEW_API_URL, changed the internal port, moved a mounted directory, or altered a required secret. The old binary may be intact but impossible to start with today’s configuration.
Do not print secret values to compare them. Compare variable names, presence, checksums where appropriate, and configuration revisions in the secret manager or Coolify UI. If a setting must be changed, record it as a separate recovery action with its own rollback value.
5. Quiesce stateful work when required
If compatibility is uncertain, put the application into its supported maintenance mode, pause consumers, or temporarily stop the producer of new writes. The exact mechanism belongs to the application—not a blanket firewall rule copied from a tutorial.
Drain or account for queued work before switching versions. Old workers may not understand payloads emitted by the new release, while redelivery can duplicate side effects such as emails or payments. Inspect idempotency guarantees and dead-letter handling rather than deleting a queue to make an error disappear.
6. Deploy the retained image through Coolify
In Configuration → Rollback, select the identified working image, start the rollback, then follow the new operation under Deployments. Treat its deployment identifier as an opaque value and watch that specific operation reach a terminal status.
Do not manually replace the Coolify-managed container during a normal rollback. That bypasses the deployment ledger and risks losing environment, network, labels, health configuration, and proxy routing. If the normal path is unavailable during a genuine incident, a manual container recovery requires a separate, carefully recorded procedure and immediate source-of-truth reconciliation.
7. Understand what health checks can and cannot prove
For eligible application deployments, Coolify’s rolling-update flow can start the replacement container, wait for its health check, and only then stop the current one. If the replacement fails, Coolify can remove it and keep the healthy version. Its documentation also notes that this application-level rolling-update sequence is not supported for Docker Compose applications.
A useful readiness check catches startup and dependency failures, but 200 OK on /health does not prove login, writes, migrations, queue processing, or external integrations. Keep the endpoint lightweight, use a realistic startup grace period, and do not make it disclose private dependency details.
8. Verify the restored release at every state boundary
After Coolify reports success, verify more than the homepage:
- Confirm the deployment points to the intended older image or digest.
- Check startup, health, application, worker, and migration logs for new errors.
- Fetch a unique release marker or expected heading, not merely an HTTP status.
- Exercise one read and one controlled write through the critical user flow.
- Confirm the write appears correctly in the database or persistent store.
- Verify queue depth and worker success if asynchronous work is involved.
- Check error rate and latency for long enough to cross the normal traffic path.
curl --fail --silent --show-error \
'https://app.example.com/health'
curl --fail --silent --show-error \
'https://app.example.com/release-check?verify=rollback' \
| grep 'EXPECTED_RELEASE_MARKER'
Use a non-sensitive canary record for the write test and remove it through the application’s normal path. Do not paste production database credentials into ad hoc shell commands or reports.
9. Stabilise, then repair the source of truth
An image rollback restores service but does not fix the branch that produced the failed release. Decide whether to revert the bad commit, create a corrective commit, or disable the release behind a tested feature flag. Push that decision to the configured Git branch and run the normal deployment path.
Otherwise the next webhook or manual deploy can reintroduce the fault. Keep the successful rollback deployment, failed commit, current branch head, migration state, and any temporary configuration changes linked in the incident record.
A compact Coolify rollback checklist
- Identify the failed deployment, commit, image, and affected flow.
- Confirm the previous working image exists in Coolify’s rollback view.
- Classify database, volume, queue, cache, and external-service changes.
- Back up state and pause risky writes when compatibility is uncertain.
- Check the old image against current environment, mounts, ports, and health settings.
- Start the retained-image rollback through Coolify and follow its deployment record.
- Verify image identity, logs, health, unique content, a read, and a controlled write.
- Resume workers and traffic only after their data contracts are proven.
- Repair Git and document temporary configuration or migration decisions.
- Review image retention and practise database restore separately.
Authoritative references: Coolify’s official guides to rollbacks, rolling updates, and health checks; and Docker’s explanation of immutable image digests.