Testland
Browse all skills & agents

lambda-timeout-budget-reference

Pure-reference catalog of AWS Lambda timeout + billing semantics. Covers Lambda's hard 15-minute (900s) wall-clock limit, the timeout-vs-deadline relationship (Lambda Context.getRemainingTimeInMillis), per-invocation billing (rounded to 1ms; per-invocation + duration × memory), the memory-vs-CPU relationship (CPU scales linearly with memory), the integration-timeout cascade (API Gateway 29s → Lambda 15min; SQS visibility-timeout vs Lambda timeout), and per-runtime nuances. Use when designing a Lambda's timeout config, debugging timeout-vs-billing surprises, or sizing memory for compute-bound workloads.

lambda-timeout-budget-reference

Overview

AWS Lambda's wall-clock limit is 15 minutes (900 seconds) per invocation. Per docs.aws.amazon.com/lambda: "The maximum value for timeout is 900 seconds."

When to use

  • Designing the timeout for a new Lambda.
  • Debugging "Lambda silently truncates output" reports.
  • Sizing memory for compute-bound work.
  • Auditing API Gateway → Lambda → downstream timeout cascade.

The 15-minute limit

Per AWS Lambda docs: 900 seconds (15 minutes) absolute maximum. For longer work, use:

  • AWS Step Functions (orchestrate multiple Lambdas)
  • AWS Batch (containers; up to 14 days)
  • ECS Fargate (containers; no time limit)

Don't try to architect around the 15-minute limit; pick the right service.

Timeout vs deadline at runtime

Per docs.aws.amazon.com/lambda: the Lambda Context object exposes get_remaining_time_in_millis() (Python), getRemainingTimeInMillis() (Node/JVM). Use it to break out of work proactively:

def handler(event, context):
    while not_done:
        if context.get_remaining_time_in_millis() < 5000:
            # Save progress, return early
            save_checkpoint()
            return {"status": "partial", "checkpoint": ...}
        do_work_chunk()
    return {"status": "complete"}

The 5-second cushion lets the handler return cleanly. Without it, the Lambda is force-killed at timeout and the caller gets a 504-equivalent.

Billing semantics

Per docs.aws.amazon.com/lambda:

Cost componentDetail
Request charge$0.20 per 1M requests (us-east-1)
Compute chargeMemory-class × GB-seconds (per ms)
Init durationFree; not billed (per AWS)

GB-second formula: memory_GB * duration_seconds.

A 512MB Lambda running 1000ms costs: 0.5 GB * 1.0 sec * $0.0000166667/GB-s = $0.00000833

Per million invocations at 1s, 512MB: $8.34 (+ $0.20 request) = $8.54.

Init duration billing was free as of 2023; this skill cites current docs.

Memory ↔ CPU relationship

Per docs.aws.amazon.com/lambda: "The amount of CPU available to a function is proportional to the memory you allocate to it. At 1,769 MB, a function has the equivalent of one vCPU."

Up to ~1769MB, you're paying for "memory" but getting "CPU." Compute-bound workloads should size memory by CPU need, not memory need.

A 256MB Lambda has ~14% of one vCPU. A 1.769GB Lambda has 1 full vCPU. A 3.5GB Lambda has 2 vCPUs.

The cost-vs-performance sweet spot is usually at the memory class where wall-clock time stops dropping (often 1024-2048MB for typical workloads).

Integration cascade

Lambda is rarely invoked directly; the integration's timeout is often the operational ceiling:

IntegrationTimeoutLambda config
API Gateway (REST + HTTP API)29 seconds (hard)Lambda timeout MUST be < 29s
Application Load Balancer4 seconds default; configurable to 4000sConfigurable both sides
CloudFront (Lambda@Edge viewer-request/response)5s for viewer functions; 30s for originTight viewer limit
SQS (event source)Configured per queue; default 30s visibilityLambda timeout < visibility timeout
DynamoDB Streams6 hours batch windowLambda timeout per-batch limit
EventBridge (async)Async; retries on timeoutIdempotency required
Step FunctionsEach task has its own timeout; default 60sPer-task tuning

The API Gateway 29-second hard limit is the most-encountered surprise: a Lambda configured for 60s still times out at 29s because API Gateway gives up first.

Testable behaviours

BehaviourTest
Lambda completes within timeout under prod loadRun k6 / Lambda Test against deployed function
Graceful return via remaining-time checkInject artificial slowness; verify handler returns "partial" not 504
API Gateway 29s budget honouredTest long-running endpoint via API GW URL; assert ≤ 29s
SQS visibility-timeout > Lambda timeoutForce a timeout; observe re-delivery from SQS
Memory tuning sweet spot foundRun at 256/512/1024/2048 MB; chart duration
Cost at p99 within budgetLatency × memory × invocations × price-per-GB-s

Anti-patterns

Anti-patternWhy it failsFix
Lambda timeout = max (900s) for "safety"Stuck Lambdas burn 15min before failing; concurrent-execution limits hitMatch timeout to actual p99 + buffer
Lambda timeout > API Gateway timeoutAPI GW kills first; Lambda runs unusedTimeout < 29s for API GW
SQS visibility-timeout < Lambda timeoutMessage re-delivered while in-flight → duplicate processingVisibility > Lambda timeout × 6 (AWS recommendation)
No get_remaining_time_in_millis() checkForce-kill at timeout; no progress savedAlways check + early-return
Sizing memory by RAM need onlyCompute-bound work wastes timeTune by p95 duration
Treating init time as billedOut of datePer current AWS docs, init is free
Cost calculation ignoring p99"It's $5/million on average" but p99 spikes blow budgetCalculate against p99 not avg

Limitations

  • Lambda is hard-killed at timeout. No SIGTERM grace; the process is frozen. Plan around this.
  • Init phase rules can change. AWS has changed Init billing historically; check current pricing.
  • Per-region pricing varies. Above examples are us-east-1; ap-northeast-1 / eu-* differ.
  • Cold-start latency adds to budget. Per cold-start-budget-reference, cold start time is billed compute time as Init phase (currently free, but counted in Init Duration).
  • Workers / Edge / Vercel have different timeout models. Cloudflare Workers: 10ms CPU time on free, 50ms on paid, 30s wall-clock total. Vercel Edge Functions: 30s wall-clock max.

References