An Immich database that is merely slow may need routine PostgreSQL maintenance or a resource fix; a database that shows repeatable integrity or recovery failures may need restoration or replacement from a verified backup.
Do not use “rebuild the database” as a generic performance fix. First separate normal growth, bloat, stale statistics, blocked maintenance, and storage latency from corruption or unrecoverable cluster state. Preserve a recovery point before invasive work, measure one maintenance change at a time, and move to a clean restore only when the evidence says the current database cannot be trusted or safely repaired.
Separate Performance Decay From Integrity Failure
Begin with the exact symptom: slow searches, slow timeline queries, large database size, high disk activity, repeated PostgreSQL errors, crash recovery loops, or an Immich migration that cannot complete. Performance symptoms and integrity symptoms carry different risk and should not share the same first repair.
Confirm the host still has healthy storage, adequate free space, normal memory behavior, and no runaway Immich background job before blaming PostgreSQL. A saturated or failing disk can make a healthy database look slow and can also create real database damage if the underlying storage becomes unreliable.
Preserve logs, database version, extension versions, recent upgrade history, and a backup or snapshot before invasive maintenance. If the only database copy may be corrupt, do not run destructive cleanup just to see whether the error disappears; keep the evidence needed for a controlled restore decision.
Look for Maintenance Signals You Can Measure
Routine maintenance becomes a plausible path when the database starts and remains internally usable but query performance or disk footprint worsens over time. Useful evidence includes accumulating dead rows, tables or indexes that grow disproportionately, autovacuum that cannot keep up, stale planner statistics, or long-running maintenance blocked by other sessions.
Dead tuples, bloat, freezing pressure, blocked VACUUM, and insufficient vacuum frequency can all affect PostgreSQL maintenance and query performance. Use table-level VACUUM signals over time instead of assuming a large database file alone proves the database needs replacement.
If statistics point to one table or index, choose the least invasive supported maintenance action for that finding and measure again. Avoid jumping straight to VACUUM FULL, broad REINDEX operations, or arbitrary autovacuum tuning across the whole cluster; those actions can create locks, I/O, or extra disk demand and may not address the real bottleneck.
Confirm Whether Bloat or Index Growth Matches the Slow Path
Compare the objects involved in slow Immich operations with table and index size, row churn, and query behavior. Bloat matters when it increases the work needed to find useful rows or makes indexes less effective, but the database can also be large simply because the library and metadata are large.
Table and index bloat should be evaluated separately, because excessive bloat can increase the work required for queries without implying database corruption. Use measured PostgreSQL bloat checks to target an observed object and refresh planner statistics where appropriate rather than treating total database size as the diagnosis.
After maintenance, rerun the exact Immich action that was slow and compare both user-visible latency and database/storage behavior. If the operation does not improve, restore the previous tuning where possible and investigate storage, query patterns, background jobs, or application-level causes rather than stacking more database changes.
Escalate to Restore or Replacement When Integrity Is Uncertain
Replacement is justified by evidence that the current PostgreSQL state cannot be trusted or recovered safely, not by age alone. Examples include repeatable page or checksum corruption, startup or recovery failures that persist on healthy storage, a damaged cluster after an incomplete storage event, or a migration state that cannot be repaired using the supported path.
Before declaring the database lost, prove that a known-good backup can restore into a clean, compatible PostgreSQL environment and that Immich can read it. If the clean restore works while the current cluster repeats the same integrity failure, you have a much stronger case for replacing the database state rather than continuing in-place repair.
Repair localized, reversible faults while preserving uncertain persistent state; rebuild only when the recovery source is verified and the target is reproducible. Apply that Immich repair-versus-rebuild boundary to the database as well. “Replacement” should mean restoring compatible PostgreSQL state from a known-good source, not switching databases because a query became slow.
Validate the Database Through Read, Write, and Backup Operations
Whether you performed maintenance or restored a clean database, validate the result through Immich rather than stopping at a successful PostgreSQL startup. Open old albums and assets, run searches, load representative videos, and verify that users and sharing state appear as expected.
Perform one safe new write, such as uploading a disposable asset, and confirm it remains accessible after a normal service restart. Watch PostgreSQL and Immich logs for recurring integrity, migration, extension, or permission errors while the read and write paths are active.
Finally, create a fresh database backup using your normal method and restore-test it on an isolated target when practical. The maintenance or replacement decision is complete only when the current system is usable and the next recovery point is demonstrably healthier than the state that triggered the incident.
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.

