
# Lambda concurrency

How many containers [Lambda](/docs/services/lambda/index.md) will run at once, and what happens to
an invocation that cannot get one.

## The limits

These size the pool to your Docker host. They are not AWS's account quota, which
Overcast does not emulate.

| Limit | Environment variable | Default | When reached |
| --- | --- | --- | --- |
| Containers across all functions | `LAMBDA_MAX_INSTANCES` | auto (25 fallback) | Reclaim an idle container → queue → throttle |
| Containers for one function | `LAMBDA_MAX_INSTANCES_PER_FUNCTION` | auto (10 fallback) | Queue → throttle |
| Aggregate container memory (Σ `MemorySize`) | `LAMBDA_MAX_MEMORY_MB` | auto (unlimited fallback) | Reclaim an idle container → queue → throttle |
| Idle containers kept per function | `LAMBDA_MAX_WARM_INSTANCES` | 10 | Surplus destroyed on release |
| Concurrent container starts | `LAMBDA_DOCKER_MAX_CONCURRENT_STARTS` | auto (4 fallback) | Starts queue behind a semaphore |
| `ReservedConcurrentExecutions` | per function, AWS API | unset | Throttle immediately |

Derivations and every other `LAMBDA_*` variable are in the
[environment variable reference](/docs/configuration/reference/index.md).

An invocation that cannot get a container first reclaims the least-recently-used
idle one — never a provisioned one — and then waits. If it is still waiting when
the function's timeout expires it is throttled, with a 429
`TooManyRequestsException` and `Reason: ConcurrentInvocationLimitExceeded`.

## The memory budget

`LAMBDA_MAX_MEMORY_MB` counts bytes, not containers: a new container is admitted
only while `Σ MemorySize` of live containers plus its own stays inside the
budget. Each container is hard-capped at its function's `MemorySize` with swap
disabled, so the sum is a real bound.

Above ~90% of the budget the pool changes behaviour: a container whose invocation
has just finished is destroyed rather than kept warm, so queued work regains
budget without waiting for the 15-minute idle sweep. Provisioned environments are
always kept and a running invocation is never interrupted. Entering and leaving
that regime is logged once each — expect cold starts while it lasts.

## Reserved concurrency

`ReservedConcurrentExecutions` is enforced with AWS's semantics rather than the
pool's: no queueing, an immediate 429 with
`Reason: ReservedFunctionConcurrentInvocationLimitExceeded`. Setting it to 0
disables the function, the same idiom that works on AWS.

Asynchronous invocations are never throttled back to the caller — they were
already answered 202 — and are retried internally. Event source mappings behave
the same way: a throttled batch is left in flight, so the messages return on the
visibility timeout. [Event delivery and retries](/docs/services/lambda/async/index.md) covers the retry
budget and where an exhausted event ends up.

## Provisioned concurrency

Environments are created in the background (`Status: IN_PROGRESS`, then `READY`),
held open regardless of the idle sweep, replenished when one is lost, and rebuilt
against the new configuration after a code or config update. Containers report
`AWS_LAMBDA_INITIALIZATION_TYPE=provisioned-concurrency`, the variable Powertools
and similar libraries read to classify a cold start.

Provisioned concurrency is a **floor, not a ceiling**: when all reserved
environments are busy, further invocations spill over into on-demand capacity with
a cold start rather than being throttled, matching AWS, where only reserved
concurrency caps a function. A reservation is never reclaimed for another
function. Without Docker nothing can be allocated, so the configuration is stored
and reported `Status: FAILED` with a `StatusReason` rather than claiming `READY`.

## Related

- [Lambda](/docs/services/lambda/index.md) — quick start and what works
- [Lambda limitations](/docs/services/lambda/limitations/index.md) — the divergence table
- [Lambda execution environments](/docs/services/lambda/execution-environments/index.md) — when a warm container is retired
- [Lambda event delivery and retries](/docs/services/lambda/async/index.md) — what happens to a throttled event
- [Lambda troubleshooting](/docs/services/lambda/troubleshooting/index.md) — throttles, layer errors, extension endpoints
- [Environment variable reference](/docs/configuration/reference/index.md) — every `LAMBDA_*` variable
