CodeVetter
← All unpacks
CodeVetter · Repo Unpack evidence

immich-app/immich

Scanned commit d6d0947383 dated 2026-09-22 — last upstream commit. Generated by codevetter 1.12.0 on 2026-09-22.

github.com/immich-app/immich ↗ · 3129 files · 25.3 MB

High performance self-hosted photo and video management solution Català Español Français Italiano 日本語 한국어 Deutsch Nederlands Türkçe 简体中文 正體中文 Українська Русский Български Português Brasileiro Svenska العربية Tiếng Việt ภาษาไทย മലയാളം [!WARNING] ⚠️ Always follo

Deep analysis by swe-2 via the devin CLI on 2026-09-22 (runtime not recorded) — every claim below links to its cited source files.

Overview

Immich is a self-hosted photo and video backup/management platform (Google Photos alternative) structured as a pnpm+mise monorepo. A NestJS/TypeScript server exposes a REST API and BullMQ background workers on Postgres (pgvector/VectorChord) and Redis, a SvelteKit web app and a Flutter mobile app consume a generated OpenAPI SDK, and a separate Python/FastAPI 'machine-learning' microservice runs ONNX models for CLIP search, facial recognition, and OCR. The stock deployment is four docker-compose services: immich-server (port 2283), immich-machine-learning, valkey (Redis), and a pinned Postgres image with vector extensions.

System map

The system is a multi-process Node.js backend plus three satellite frontends/services. A supervisor in server/src/main.ts forks an 'api' child process and spawns 'microservices'/'maintenance' worker_threads (ImmichWorker enum), each booting a different Nest module from app.module.ts. The API worker serves REST under /api, static web assets via sirv, and socket.io websockets; the microservices worker runs BullMQ consumers over Redis. Persistence is Postgres accessed through Kysely with a hand-maintained schema (server/src/schema) and generated migrations. A Python FastAPI service (machine-learning/) performs inference, and web/ (SvelteKit) plus mobile/ (Flutter) are the user-facing clients built against a generated SDK in packages/sdk.

All 13 system map claims →

Feature catalog

Feature surface is primarily ~45 Nest controllers registered in controllers/index.ts covering assets, albums, sharing, people/faces, search, libraries, jobs, sync, auth, and admin management. Background processing is expressed as JobName jobs on QueueName queues (thumbnails, metadata, video conversion, face detection/recognition, smart search, OCR, duplicates, library scan, backups, notifications, workflows). Auth supports password login, OAuth/OIDC with backchannel logout, API keys, sessions, PIN codes, and shared-link access. A WASM plugin system (extism) plus user-defined workflows are newer extension-oriented features.

All 14 feature catalog claims →

Data flow

Data enters through Express controllers guarded by a global AuthGuard that produces an AuthDto (user, session, shared link, or API key context) via AuthService.authenticate. Uploads stream through a custom multer storage engine into StorageCore-managed folders under IMMICH_MEDIA_LOCATION, then asset rows are written through repositories over Kysely and BullMQ jobs drive metadata extraction (exiftool), thumbnail generation (sharp), transcoding (ffmpeg), and ML inference via the FastAPI service. All cross-service coordination goes through a typed EventRepository (emit/onEvent) and websocket pushes to clients; mobile/web pull changes via the sync endpoints and socket.io.

Behavior traces

Key flows were walked end-to-end. Startup goes through a supervisor that gates on a Postgres advisory lock and maintenance mode, then each worker boots its Nest module which emits AppBootstrap to ordered handlers (database migrations first, then storage, then job discovery). The upload flow traverses guard → multer interceptors → controller → service → DB + queue. Background work is decoupled: jobs land in Redis and are executed by the microservices worker via a JobRun event indirection.

Testing signals

Testing is layered: Vitest unit tests co-located as *.spec.ts in server/src and web/src, a 'medium' tier in server/test/medium that runs against a real Postgres via testcontainers, API-level e2e specs in e2e/ (Vitest + supertest-style SDK calls against a docker-compose stack), and Playwright browser/UI/maintenance projects. CI (.github/workflows/test.yml) shards jobs per changed directory. Coverage is configured but explicitly excludes some files, and several infra-heavy areas (storage.core is covered, but websocket/adapter and plugin internals have thin coverage).

Risk map

Security-sensitive surface concentrates on file upload/disk IO, auth token handling, subprocess media tooling, and the WASM plugin host. The multer storage engine writes user-supplied bytes to predictable uuid paths, ffmpeg/exiftool process untrusted media, and extism plugins run third-party WASM gated by env vars. Operational risks include a 24h request timeout, trust-proxy assumptions, startup-time migrations under an advisory lock, and a supervisor that kills the whole process on worker failure. Several safety rails exist (mandatory @Authenticated, duplicate-job startup validation, constant-time login compare) but are themselves fragile coupling points.

All 14 risk map claims →

Extension points

The codebase is organized around explicit registries: controllers/index.ts, services/index.ts, repositories/index.ts, commands/index.ts, plus decorator-driven registration (@OnJob, @OnEvent, @Endpoint, @Authenticated). Adding an endpoint means a controller method + zod DTO + index registration; adding a job means enum entries + @OnJob handler (enforced at startup). A WASM plugin system via @immich/plugin-sdk and workflows provide runtime extensibility, and the OpenAPI→SDK codegen pipeline propagates API changes to all clients.

All 13 extension points claims →

Contributor handoff

This is a large, convention-heavy monorepo — change one layer and the generated artifacts (OpenAPI spec, SDK, migrations, mobile client) must be regenerated and kept in sync or CI fails. Server code follows strict layering (controller → service → repository → Kysely) with decorator-driven registration that will fail loudly at startup if misconfigured. Tests are fast to run per-package but e2e/medium tiers need Docker. Read the bootstrap and decorator machinery before editing anything structural.

Languages

LanguageFilesShare of source
TypeScript107164%
Svelte41625%
JSON168docs/config
Markdown124docs/config
YAML53docs/config
SQL362%
Kotlin352%
Python342%

Start reading here

Probable source entrypoint: packages/ — inferred from the directory tree and manifest, not the upstream docs.

Source roots

packages/ (62 files)

Repository structure

Top-level pathFiles
mobile/1121
web/739
server/728
docs/127
i18n/89
e2e/84
packages/62
machine-learning/51

Docs found: CONTRIBUTING.mdREADME.mddocs/README.mddocs/docs/administration/backup-and-restore.mddocs/docs/administration/jobs-workers.mddocs/docs/administration/maintenance-mode.mddocs/docs/administration/oauth.mddocs/docs/administration/postgres-standalone.mddocs/docs/administration/reverse-proxy.mddocs/docs/administration/server-commands.md

Package

package.json — immich-monorepo v3.2.0, 2 declared dependencies.

prettierprettier-plugin-sort-json

CI & config entrypoints

Structural health signals

Average score 6.5/10 across 96 analyzed source files; 46 hotspots surfaced.

These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.

Recent history