There is no useful universal number of concurrent Immich users that every home server can handle, because “one user” can mean idle browsing, face search, a large upload, video playback, or several background jobs at once.
Capacity should be measured as the highest repeatable household workload that still meets your own response-time and error criteria. Establish a quiet baseline, replay realistic mixed actions, raise concurrency in controlled steps, and watch the first saturated resource. That gives you a defensible capacity range for your hardware and library instead of a made-up user limit.
Define What “Slows Down” Before Counting Users
Choose a small set of user-visible actions that matter in your home: opening the timeline, loading an older album, search, video playback, and uploading a batch. Decide what failure looks like before the test, such as unacceptable latency, timeouts, failed uploads, playback stalls, or a queue that keeps growing after users stop.
Do not mix foreground and background work without recording it. Thumbnail generation, video transcoding, face processing, Smart Search, library scans, database maintenance, and backups can consume the same CPU, memory, disk, and network resources as active users. A “four-user” test during a large import is a different workload from four people browsing a settled library.
Record the hardware, Immich version, database placement, storage type, network link, library size, and active background jobs with every result. Without that context, a concurrency number cannot be compared meaningfully after an upgrade or to another home server.
Measure a One-User Baseline With Background Work Under Control
Start when the system is in a known state and measure one representative user journey. Capture client response time together with server CPU, memory pressure, disk latency or utilization, network throughput, database activity, and any Immich worker queues you can observe.
A capacity statement is meaningful only when the workload, test duration, and success criteria are explicit. Use workload-based capacity testing to save a one-user baseline, then measure how latency, throughput, and errors change as concurrency rises.
If one user is already slow, stop the concurrency test. Fix the single-user bottleneck first; adding more sessions only magnifies an existing storage, database, CPU, network, or configuration problem and tells you little about the server’s true scaling behavior.
Raise Realistic Concurrency in Controlled Steps
Add users or scripted client sessions gradually while keeping the action mix similar between steps. A useful household sequence might double the active sessions from a small baseline, but the exact numbers are less important than changing only concurrency and holding the workload definition constant.
Define latency, error, and throughput limits before testing, and use realistic multi-step journeys instead of hammering one endpoint. A realistic load-testing workload for Immich should mix the actions your household actually performs rather than treating repeated login requests as a proxy for photo-server capacity.
Hold each step long enough for caches, queues, database connections, and storage demand to settle. Record both the peak and whether the system recovers when load is removed. A server that looks acceptable for a short burst but leaves a growing job queue is already beyond a sustainable level for that workload.
Identify the First Resource That Saturates
When latency jumps, correlate the timestamp with resource behavior. CPU saturation during search or machine learning suggests compute pressure; high disk latency with modest CPU points toward database or media storage; full network links point toward transfer or remote-access limits; rising database waits or connection pressure point toward the data layer.
Background jobs can change the result because thumbnailing, transcoding, machine learning, scans, backups, or retry loops may consume resources even when no one is actively browsing. Compare the test with Immich background-load conditions controlled so you do not mistake scheduled work for a low user limit.
Do not “fix” capacity by hiding errors with longer client timeouts. Change the limiting resource or workload policy—such as scheduling heavy jobs, improving storage placement, reducing simultaneous transcodes, or adding compute—then replay the exact failed step to prove that the bottleneck moved or disappeared.
Set a Practical Household Capacity Range and Re-Test It
Define practical capacity as the highest tested concurrency at which all required user journeys stay inside your prewritten latency/error limits, queues return toward baseline after the test, and the host retains enough headroom for ordinary background work. Report it as a workload-specific range, not an Immich-wide maximum.
Repeat the boundary step at least once from a clean, comparable state and include the actions that previously caused degradation. Then test the next-higher step briefly enough to confirm the boundary still appears in the same resource, without driving the system into an uncontrolled queue or storage-pressure event.
Rerun the same test after major Immich upgrades, database moves, storage changes, hardware changes, or a large increase in library size. Your capacity number is a property of the current system and workload; keeping the test recipe is more valuable than keeping an old user count.
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.

