Lambda Reserved Concurrency: Bulkheads That Protect Tenant Workloads

Lambda Reserved Concurrency: Bulkheads That Protect Tenant Workloads

Account concurrency is a shared fate pool. One tenant’s report export or AI agent fan-out will starve checkout if you leave every function unreserved. Bulkheads via reserved concurrency are the unfair advantage: explicit partitions for critical paths, unreserved headroom for bursty best-effort work, and alarms before the pool hits zero.

⚡ TL;DR: Reserve concurrency for auth, checkout, and payment webhooks first. Cap noisy neighbors (exports, backfills, agent tools) with low reserved ceilings or separate accounts. Leave unreserved headroom for spikes — reserved is subtracted from the account pool. Simulate noisy-neighbor drills. Tie agent backends to Lambda Warm Pools and sandboxes in Secure AI Sandboxes.

Mental model: reserved subtracts from the pool

Account limit L (e.g. 1000)
Reserved sum R across functions
Unreserved capacity = L - R

Function with reserved=50 can never exceed 50
Function with no reservation competes for L - R
// GOOD: critical path reserved; batch capped
await lambda.putFunctionConcurrency({
  FunctionName: "checkout-api",
  ReservedConcurrentExecutions: 200,
});
await lambda.putFunctionConcurrency({
  FunctionName: "tenant-export",
  ReservedConcurrentExecutions: 20, // hard bulkhead
});

// BAD: reserve 900 of 1000 for "important" batch jobs
// leaves auth/checkout fighting over 100 unreserved

✅ Reserve the money path; cap the analytics path.
❌ Reserving almost everything “just in case” (destroys burst capacity).

Per-tenant isolation patterns

Pattern When Tradeoff
Reserved concurrency per function Feature-level bulkhead Coarse
Separate functions per noisy tenant tier Enterprise isolation Ops overhead
SQS max concurrency on ESM Async pipelines Backpressure into queue
Provisioned + reserved Latency + isolation Cost
// Event source mapping max concurrency as a second bulkhead
await lambda.updateEventSourceMapping({
  UUID: esmId,
  ScalingConfig: { MaximumConcurrency: 10 },
});

For multi-tenant SaaS, do not invent “dynamic reserved concurrency per tenant” on every request — use queue depth, per-tenant rate limits, and tiered function aliases instead.

Drill the failure mode

# Synthetic load on export while measuring checkout Availability + Throttles
aws cloudwatch put-metric-alarm --alarm-name checkout-throttles \
  --metric-name Throttles --namespace AWS/Lambda \
  --dimensions Name=FunctionName,Value=checkout-api \
  --threshold 1 --comparison-operator GreaterThanOrEqualToThreshold \
  --evaluation-periods 1 --statistic Sum --period 60

If checkout throttles while export is healthy, your bulkhead math is inverted.

Closing checklist

  • [ ] Money-path functions have reserved concurrency documented in an ADR
  • [ ] Noisy jobs capped (reserved low or ESM max concurrency)
  • [ ] Sum(reserved) leaves intentional unreserved headroom
  • [ ] Alarms on Throttles for critical functions
  • [ ] Quarterly noisy-neighbor game day
  • [ ] Agent/tool Lambdas isolated from interactive APIs

Related reading

Last updated on September 11, 2026


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply