Skip to main content
Capacity is containers times what each container handles at once, and both start at one. Without scaling settings, a .map() over 500 inputs runs them one after another. Per-kind defaults are in Resources and options.

Concurrency inside one container

Functions

concurrency is how many calls one container serves at once. Each call gets its own process, so CPU-bound calls run in parallel and a crash stays contained. in_process=True runs them as threads in one interpreter instead, so a model loaded once in on_start serves every slot:
Threads share the GIL, so this pays off when calls spend their time in a GPU kernel, a network call, or a C extension. Cancelling one call in a shared interpreter stops the container, and the other calls in it retry.

Endpoints and ASGI apps

A container runs workers server processes, and each takes concurrency requests at once, or concurrent_requests on ASGI and realtime. Workers don’t share memory, so each loads its own copy of a model in on_start.
A GPU model fits workers=1 with higher concurrency. A CPU-bound handler fits one worker per CPU and a concurrency of one or two. Async and I/O-bound code takes a high concurrency in one worker.

More containers

Autoscaler sets how many containers a workload may run:
The autoscaler runs one container per tasks_per_container queued calls, up to max_containers. It fits best at the container’s real concurrency, which is concurrency for a function and workers * concurrency for an endpoint. Here, 500 inputs from .map() run on 20 containers, 4 at a time each. Without an autoscaler, a workload runs at most one container. With one, tasks_per_container defaults to 1, so it’s worth setting. Pods scale by hand with lazycloud deployment scale. See Pods.

Warm containers

An idle container stays up for keep_warm seconds so the next call skips the start, which can take a minute for a model server. Functions default to 10 seconds, endpoints to 180, and scheduled functions to 0. You pay for warm containers while they run. min_containers keeps containers running even with no work, so the first call after a quiet hour doesn’t wait:

When the queue is full

max_pending_tasks, 100 by default, caps queued and running calls per workload. Past it, a function call fails with a capacity error and an endpoint returns 429. .map() submits every input up front, so a batch of 500 needs a cap of at least 500. A queued function call waits up to its timeout_seconds for a container, and an endpoint request waits up to its timeout_seconds, 180 by default, for a free slot. After five seconds, the CLI and dashboard show why a call is waiting.

Patterns

Batch over many inputs

One call per container keeps a crash or an out-of-memory kill to one input.

GPU model over HTTP

One worker loads the model once, eight requests share it, and one container stays warm for the first request of the day.

CPU API with steady traffic

Four workers on four CPUs, 32 async requests each, and a new container per 128 in flight.

Long-running job

retries=0 avoids repeating six hours of work, and preemptible=False keeps the machine from being reclaimed mid-run. Checkpoints in a volume let a new run resume.