A known-good Immich database backup is useful only if you restore it into a controlled state and prove that the recovered database still points to the media your server can actually see.
Treat recovery as a sequence, not a single import command. Preserve the failed instance first, identify the Immich version and backup timestamp, bring up a clean compatible database target, restore without letting the application write into an empty schema first, then validate accounts, timeline data, media paths, and one new write. If any step is ambiguous, stop before replacing the last recoverable copy.
Freeze the Failed State Before You Restore Anything
Stop new uploads and background writes to the affected Immich instance before recovery work begins. Save the current Compose file, environment values, mounted paths, image versions, recent logs, and the damaged database state if storage permits. A failed database can still contain evidence that explains what happened, and overwriting it removes that evidence.
Identify exactly which backup you intend to trust. Record its timestamp, how it was created, its file size, and whether it was ever test-restored. A SQL dump produced by the database is a different recovery asset from a raw copy of the live PostgreSQL data directory; do not treat them as interchangeable.
Create the recovery target in a separate directory or isolated stack whenever possible. The exit condition for this stage is simple: the original failed state is preserved, the chosen backup is read-only, and you know which deployment version and storage paths the restore is meant to reconnect.
Check That the Backup Is Actually Restorable
Inspect the backup before replaying it. A compressed SQL dump should decompress cleanly and contain recognizable PostgreSQL dump content rather than being an empty archive produced by a failed pipeline. If you have checksums or repository verification results, compare them now instead of discovering corruption halfway through recovery.
A PostgreSQL dump is a safer recovery asset than a casual copy of a live database directory because it is created through database-aware tooling and can be replayed into a clean target. The database-dump backup pattern also keeps the database separate from the media copy, making it easier to validate each half before recovery.
Also confirm that the media and configuration belonging to the backup window still exist. Restoring the database alone can recover users, albums, metadata, and file references while leaving every asset broken if the referenced library paths are missing. Proceed only when the dump and the media/configuration set belong to a known recovery point.
Start a Compatible Clean Database Target First
Match the restore method to the version that created the backup. Current Immich releases provide database restore through Administration > Maintenance and through the fresh-install onboarding flow, while older backups may require version-specific manual instructions; the restore workflow changed in v2.5.0.
For a fresh recovery target, do not let Immich run normal migrations against an empty schema before the database restore is ready. If your deployment method starts the application together with PostgreSQL, use the version-appropriate restore controls so the server does not create competing state before import.
If the database will not become healthy on its own, stop and resolve that first. Do not keep replaying the same backup into a target that is restarting, out of disk space, or using an incompatible storage layout. A clean, stable target is a prerequisite, not a troubleshooting side quest.
Restore the Dump Once and Stop on the First Error
Restore the chosen dump into the prepared database and capture the complete output. Use the database tooling and flags appropriate to the dump format so an error causes the restore to fail visibly instead of leaving a partially imported schema that still starts.
A usable migration set needs the assets, PostgreSQL state, and the configuration that reconnects them. A complete Immich backup set includes uploaded assets, a supported database backup, and deployment configuration, with restore testing used to prove the set works. Keep those pieces together so the destination can be matched to one recovery point.
After a successful import, start the Immich application and watch its first startup closely. If the interface asks you to create a new first administrator instead of accepting the existing accounts, stop: that strongly suggests the restored database is not the one Immich is using. Do not begin re-uploading photos into that empty state.
Validate Database State, Media Paths, and a New Write
Log in with an existing account and sample the timeline across old and recent dates. Open several originals, inspect albums or favorites that you know existed, and confirm that the application can resolve the underlying files rather than only displaying database rows.
Database state, application files, configuration, and uploads have to agree at restore time. Use a consistent database-container backup as the acceptance model, not simply whether PostgreSQL starts.
Finally upload one disposable photo, wait for normal processing, confirm it survives an Immich restart and a host reboot, then delete it through the application. If accounts, old assets, and the new write all behave normally, take a fresh backup of the recovered state before any version upgrade. If not, return to the preserved failure evidence or an older known-good backup rather than compounding the damage.
Support & Tips
More to Read

How to Optimize Immich Database Connections for Concurrent Containers
Do not raise max_connections first. Measure Immich sessions, total every container's demand, preserve admin headroom, and tune only the proven bottleneck.

How to Prevent Duplicate Jobs or Imports in Immich
Separate repeated jobs from duplicate assets. Use one canonical ingestion path, control retries and path changes, then test re-entry on a small cohort.

How to Repair Immich After Its Database Volume Fills Up
Never delete PostgreSQL WAL to free space. Stop Immich writes, preserve database state, add safe capacity, recover PostgreSQL, then prevent recurrence.

