CodeVetter · Repo Unpack · System map
immich-app/immich
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.
- server/src/main.ts is the process supervisor: Workers.bootstrap() checks maintenance mode, waits on a Postgres advisory lock (DatabaseLock.MaintenanceOperation via pg_try_advisory_lock), then starts each enabled worker — the API worker via child_process.fork and other workers via worker_threads.Worker.
- Three runtime worker types exist: ImmichWorker.Api, ImmichWorker.Maintenance, and ImmichWorker.Microservices; the set to run is configurable via IMMICH_WORKERS_INCLUDE/IMMICH_WORKERS_EXCLUDE env vars parsed in EnvSchema.
- app.module.ts defines four Nest modules: ApiModule (controllers + AuthGuard + FileUploadInterceptor), MicroservicesModule (BullMQ + SchedulerRegistry), MaintenanceModule (minimal providers + MaintenanceAuthGuard), and ImmichAdminModule (nest-commander CLI commands).
- configureExpress() in app.common.ts wires the HTTP stack: trust proxy settings, helmet from helmet.json, cookieParser, 10mb JSON/urlencoded limits, global 'api' prefix with excludePaths, a custom socket.io WebSocketAdapter, swagger, sirv static serving of the built web app, SSR fallback, compression, and a 24-hour requestTimeout.
- Postgres is accessed through Kysely (kysely-postgres-js driver); the schema is declared in code under server/src/schema/tables and migrations live in server/src/schema/migrations managed by @immich/sql-tools CLI scripts (migrations:generate/run/revert).
- Redis (valkey image in compose) backs BullMQ queues and the socket.io pub/sub adapter; ConfigRepository.getEnv() builds bull.config, bull.queues, and redis options from environment.
- The machine-learning service is a standalone FastAPI app (immich_ml/main.py) exposing GET /ping and POST /predict; it keeps an in-memory ModelCache of ONNX models, runs inference on a ThreadPoolExecutor, and can idle-shutdown after model_ttl seconds.
- The web frontend is SvelteKit + Vite + Tailwind 4; in dev it proxies /api, /.well-known/immich, and /custom.css to IMMICH_SERVER_URL (default http://immich-server:2283), and in production the API server serves the static build via sirv.
- The mobile app is Flutter/Dart (pubspec sdk '>=3.12.0 <4.0.0', flutter 3.47.2) using riverpod, auto_route, drift sqlite, and a generated openapi package at mobile/generated/openapi.
- Standard deployment is docker/docker-compose.yml with services immich-server (port 2283, mounts UPLOAD_LOCATION at /data), immich-machine-learning (model-cache volume), valkey redis, and Postgres 14 image 'postgres:14-vectorchord0.4.3-pgvectors0.2.0'.
- The workspace is orchestrated by pnpm (pnpm-workspace.yaml) and mise (mise.toml pins node 24.21.0, pnpm 11.24.0, java, jellyfin-ffmpeg, extism/binaryen toolchains); server scripts are nest build / vitest, web scripts are vite build / vitest.
- The OpenAPI spec open-api/immich-openapi-specs.json is generated by booting ApiModule in preview mode and writing the swagger document (server/src/bin/sync-open-api.ts); mise task open-api-typescript runs oazapfts to regenerate packages/sdk/src/fetch-client.ts used by web, cli, and e2e.
- An admin CLI ('immich-admin') is dispatched in main() before worker bootstrap: it sets process.title 'immich_admin_cli', forces log level Warn, lazily imports ImmichAdminModule, and runs nest-commander commands such as reset-admin-password, grant-admin, password-login, oauth-login, maintenance-mode, and media-location.