Immich
Self-hosted photo and video backup with real phone apps, face search and semantic search
Immich backs up photos and videos from iOS and Android to your own server and gives you a timeline, albums, face grouping and natural-language search over your library. It is the closest self-hosted equivalent to Google Photos, including the background upload behavior people actually depend on.
Our verdict on Immich#
Immich stopped being a moving target on 1 October 2025, when v2.0.0 shipped as the first stable release and the project adopted semantic versioning: any 2.x app now talks to any 2.x server. That is the single biggest operational change in its history, and it means the old ritual of reading release notes before every single pull is now only mandatory across majors. It still bites. v3.0.0 (2 July 2026) dropped pgvecto.rs entirely, so anyone coming from before 1.133.0 has to migrate to VectorChord first, and it moved the amd64 ML image to an x86-64-v2 baseline. Budget the RAM honestly: the docs ask for 6 GB minimum, 8 GB recommended, and the immich-machine-learning container is most of that. On arm64 it runs, but GPU acceleration is limited to Mali via ARM NN or RK3588-class Rockchip via RKNN. CUDA, OpenVINO and ROCm are x86-64 only.
Who Immich is for#
Choose it if
- Households leaving Google Photos who need reliable background upload from several phones, not a manual import workflow
- Anyone with 100k+ images who wants face grouping and 'photo of a red bicycle in snow' search running locally
- Homelabbers with an x86-64 box, 8 GB of RAM to spare and an SSD for Postgres
- People who want an app store presence and a phone client their family will actually tolerate
Look elsewhere if
- Your server has 4 GB of RAM or less and you want ML features; you can run with machine learning disabled, but that removes search and face grouping
- You need Postgres on network storage or a shared managed database instance; the docs rule out both
- You want a read-only viewer over an existing folder tree with no database to maintain
What running it actually looks like#
Docker Compose with four containers: immich-server, immich-machine-learning, a Valkey instance, and a pinned ghcr.io/immich-app/postgres image that bundles VectorChord. Only 2283 is published. You set UPLOAD_LOCATION and DB_DATA_LOCATION in .env before first start, and the Postgres path must be a local filesystem, not NFS or a mapped SMB share. First run creates the admin account in the browser, then you install the phone app, point it at the URL and let it back up. The first import is the expensive part: thumbnail generation, video transcoding and ML jobs all queue at once and will peg the CPU for hours. Upgrades pull new images and run migrations at startup. Downgrading afterwards is unsupported, including within a minor.
Resource profile#
- Memory
- 900 MB idle, around 3500 MB in ordinary use. Docs state 6 GB minimum and 8 GB recommended; the machine learning container holds the CLIP and face models resident and is what pushes a running instance past 3 GB.
- CPU and acceleration
- Initial import saturates every core for hours doing thumbnails, transcodes and ML inference; since v3.0.0 the amd64 machine learning image requires an x86-64-v2 CPU, so pre-2012 hardware is stranded on v2.7.5.
- Storage growth
- Thumbnails plus transcoded video add roughly 10 to 20 percent on top of your originals per the docs; the Postgres directory is typically 1 to 3 GB and must sit on local SSD, never an NFS or SMB share.
- Operational load
- 3 of 5, Moderate. Four containers including a Postgres that needs a specific vector extension, plus schema migrations on almost every release. Semantic versioning since v2.0.0 has made minor upgrades boring, but major versions still carry real breaking changes and downgrades are not supported.
Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.
Data and backup surface#
Two things matter: the originals under UPLOAD_LOCATION (the library/ subdirectory) and the Postgres database. Copy library/ live if you must, but dump the database with pg_dumpall rather than snapshotting DB_DATA_LOCATION under a running container. upload/, thumbs/, encoded-video/ and profile/ are regenerable: you can exclude thumbs/ and encoded-video/ from backups and rebuild them from the admin jobs page, at the cost of another full ML and transcode pass. External libraries are read-only references, so those source folders need their own backup. Restore order is database first, then files, then start the stack.
Derived backup shape
Postgres dump. pg_dump (or pg_dumpall) into a file, then snapshot that file plus the app's data volume.
Traps and surprises#
pgvecto.rs is gone in v3.0.0
If your instance predates 1.133.0 it is still on pgvecto.rs, and v3.0.0 removed support for it. You have to reach a VectorChord-capable version and let the migration complete before jumping to v3, and once you are on VectorChord you must not roll back below 1.133.0. The pinned Postgres image in the official compose file is the supported path; hand-rolled Postgres means installing the extension yourself.
The ML container needs an x86-64-v2 CPU
Since v3, the amd64 machine learning image is built for the x86-64-v2 microarchitecture level. Most CPUs from around 2012 onward qualify, but older Xeons and Atoms will crash the container on start. The documented workaround is pinning the ML container to v2.7.5, which still targets x86-64-v1. Server-side, arm64 is fine, but ARM boards only get GPU acceleration through ARM NN on Mali or RKNN on RK3576/RK3588.
OOM kills look like broken search
When the machine learning service dies with exit code 137 it was killed for memory, not a bug. Symptoms are searches returning nothing and face jobs stalling silently. Each additional value of MACHINE_LEARNING_WORKERS loads a second full copy of the models, so raising it roughly doubles resident memory. On constrained hosts, keep it at 1, choose a smaller CLIP model, or set IMMICH_MACHINE_LEARNING_ENABLED=false and lose search.
Emptying the trash deletes your originals
Immich's trash is not a soft view over a preserved copy. When the trash is emptied in the UI, or when the retention period expires, the original files are removed from UPLOAD_LOCATION for real. Combined with mobile clients that offer to free up space on the phone after upload, it is possible to have exactly one copy of a photo and delete it from the web UI. Immich is not a backup of itself.
Downgrades are not supported at all
The upgrade docs say plainly that downgrading to an earlier version is unsupported even within the same minor, because migrations run forward only on startup. If a release breaks something for you, the recovery path is restoring the database dump you took before the upgrade, not pulling the old tag. Take the dump first; the tag rollback alone will leave a schema the old binary cannot read.
Specifications#
- Category
- Photos, files and sync
- Licence
- AGPL-3.0 (Copyleft)
- Written in
- TypeScript / Node.js, Python (machine learning), Dart (mobile apps)
- First release
- 2022
- Maturity
- Stable
- Datastore
- PostgreSQL 14 with the VectorChord extension, plus Valkey/Redis for the job queue
- Default ports
2283- Ships as
- docker compose
- arm64 builds
- Yes
- Identity
- Native OIDC. OIDC is built into the server with claim-based storage quota and role mapping, but local password login stays on until you explicitly disable it in admin settings.
- Replaces
- Google Photos, Apple iCloud Photos, Amazon Photos, Synology Photos
- Project site
- immich.app
- Source
- github.com/immich-app/immich
- Documentation
- docs.immich.app
Alternatives to Immich#
Everything else in photos, files and sync, closest in operational weight first.
| Tool | Ops load | Idle RAM | Licence |
|---|---|---|---|
| Seafile | 3, Moderate | 700 MB | GPL-2.0 with an OpenSSL linking exception (server, Community Edition); Professional Edition is proprietary |
| Nextcloud | 4, Heavy | 600 MB | AGPL-3.0-or-later |
| PhotoPrism | 2, Light | 450 MB | AGPL-3.0 (Community Edition); default images ship under the PhotoPrism Plus License |
| File Browser | 1, Set and forget | 20 MB | Apache-2.0 |
| Syncthing | 1, Set and forget | 60 MB | MPL-2.0 |
Where Immich comes up elsewhere#
Head to head
Migration guides
Guides
- Backups that actually restore
- Choosing hardware for a home server
- Backing up a running database without corrupting it
- DNS, subdomains and split horizon for self-hosters
- Docker Compose conventions that survive year two
- GPUs, transcoding and local AI: what hardware you actually need
- Moving a self-hosted service to a new machine
- Mini PC, NAS or used enterprise gear
- What a home server actually costs to run
- Remote access without port forwarding
- Reverse proxy and TLS, done properly
- Your first self-hosted server: the decisions that are hard to undo
- Single sign-on for self-hosters: the honest state of it
- Storage layout: ZFS, btrfs, mdadm, or just one disk
- An update strategy that does not lose data
- When not to self-host
Reference
Sources#
Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.
Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.