A Lambda function that processed S3 event notifications had been running fine for months. Then last Tuesday, our alerting channel lit up with invocation failures. CloudWatch logs showed Task timed out after 3.00 seconds on every invocation. The payload hadn’t changed, the code hadn’t changed, and the downstream API was healthy. Turns out, a new batch of files had grown from 500 KB to 12 MB, and the function’s 128 MB memory allocation was forcing the runtime to swap and crawl. A quick bump to 512 MB and a timeout increase to 30 seconds fixed it instantly. In this post, I’ll walk through exactly what causes Lambda timeout and memory errors and how to fix them.
The Problem
Your AWS Lambda function is failing in production with one of these errors in CloudWatch Logs:
Task timed out after 3.00 seconds
REPORT RequestId: abc-123 Duration: 3001.50 ms Billed Duration: 3000 ms Memory Size: 128 MB Max Memory Used: 127 MB
Runtime exited with error: signal: killed
RequestId: abc-123 Error: Runtime exited with error: signal: killed
Runtime.ExitError
The function either exceeds its configured timeout or runs out of allocated memory, and the Lambda runtime kills the invocation.
| Error | Meaning |
|---|---|
Task timed out after X.XX seconds |
Function execution exceeded the configured timeout value |
Runtime exited with error: signal: killed |
Function exceeded allocated memory; the OS killed the process |
Max Memory Used close to Memory Size in REPORT line |
Memory pressure; the function is near or at its limit |
RequestId: ... Process exited before completing request |
Function crashed due to resource exhaustion or unhandled exception |
Why Does This Happen?
-
Memory allocation too low for the workload — Lambda allocates CPU proportionally to memory. A 128 MB function gets a fraction of a vCPU. If your function processes large files, parses JSON payloads, or runs data transformations, it needs more memory (and therefore more CPU) than the default.
-
Timeout set too low for downstream calls — If your function calls DynamoDB, an external API, or another AWS service, network latency and cold starts can push execution past a 3-second timeout. The default timeout is 3 seconds, which is rarely enough for anything beyond trivial operations.
-
Cold starts adding latency — When Lambda provisions a new execution environment, initialization code (importing libraries, establishing database connections) runs before your handler. In Python and Node.js this might add 200–500 ms; in Java or .NET it can add 2–10 seconds.
-
VPC-attached Lambda with slow ENI provisioning — Lambda functions inside a VPC previously suffered from long cold starts due to ENI creation. While AWS improved this with Hyperplane ENIs, functions in VPCs with misconfigured subnets or exhausted IP addresses can still experience delays.
-
Synchronous downstream service is slow or unresponsive — Your function waits on an HTTP call to an external API or a database query that takes longer than expected. Without proper timeouts on the SDK or HTTP client, the Lambda timeout is the only backstop.
-
Memory leak across warm invocations — Objects stored in global scope persist between invocations in warm containers. If your function appends to a global list or cache without cleanup, memory usage grows with each invocation until it hits the limit.
The Fix
Step 1: Identify the Failure Type from CloudWatch Logs
# Get recent invocation errors for your function
aws logs filter-log-events \
--log-group-name /aws/lambda/my-function \
--filter-pattern "?\"Task timed out\" ?\"signal: killed\" ?\"Runtime.ExitError\"" \
--start-time $(date -d '1 hour ago' +%s000 2>/dev/null || date -v-1H +%s000) \
--query 'events[*].message' \
--output text
Look at the REPORT lines to compare Memory Size vs Max Memory Used:
# Check memory usage from REPORT lines
aws logs filter-log-events \
--log-group-name /aws/lambda/my-function \
--filter-pattern "REPORT" \
--start-time $(date -d '1 hour ago' +%s000 2>/dev/null || date -v-1H +%s000) \
--limit 20 \
--query 'events[*].message' \
--output text
If Max Memory Used is within 10 MB of Memory Size, the function is memory-constrained. If Duration equals or exceeds the timeout, it is time-constrained.
Step 2: Increase Memory Allocation
# Check current configuration
aws lambda get-function-configuration \
--function-name my-function \
--query '[MemorySize, Timeout, Runtime, LastModified]' \
--output table
# Increase memory from 128 MB to 512 MB
aws lambda update-function-configuration \
--function-name my-function \
--memory-size 512
Lambda allocates CPU proportionally to memory. At 1,769 MB, your function gets one full vCPU. Doubling memory also doubles available CPU, which can reduce execution duration and sometimes even lower cost.
Step 3: Increase Timeout
# Increase timeout to 30 seconds
aws lambda update-function-configuration \
--function-name my-function \
--timeout 30
The maximum Lambda timeout is 900 seconds (15 minutes). Set the timeout to at least 2x your expected execution time to handle variance, but keep it as low as practical to avoid paying for hung invocations.
Step 4: Add Timeouts to Downstream Calls in Your Code
Do not rely solely on the Lambda timeout. Set explicit timeouts on every external call:
# Python example — boto3 with explicit timeouts
import boto3
from botocore.config import Config
config = Config(
connect_timeout=5,
read_timeout=10,
retries={'max_attempts': 2}
)
dynamodb = boto3.resource('dynamodb', config=config)
# Python example — HTTP calls with requests library
import requests
response = requests.get(
'https://api.example.com/data',
timeout=(3, 10) # (connect_timeout, read_timeout)
)
Step 5: Use AWS Lambda Power Tuning to Find the Optimal Configuration
AWS Lambda Power Tuning is an open-source tool that runs your function at different memory settings and reports cost and duration:
# Deploy the power tuning state machine (via SAR)
aws serverlessrepo create-cloud-formation-change-set \
--application-id arn:aws:serverlessrepo:us-east-1:451282441545:applications/aws-lambda-power-tuning \
--stack-name lambda-power-tuning \
--capabilities CAPABILITY_IAM
# After deployment, invoke with your function ARN
aws stepfunctions start-execution \
--state-machine-arn arn:aws:states:us-east-1:123456789012:stateMachine:powerTuningStateMachine \
--input '{
"lambdaARN": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
"powerValues": [128, 256, 512, 1024, 1769, 3008],
"num": 20,
"payload": "{\"key\": \"value\"}"
}'
This runs your function 20 times at each memory level and produces a visualization showing the cost-performance sweet spot.
Step 6: Check for Memory Leaks in Warm Containers
If memory usage climbs across invocations, inspect global-scope variables:
# Watch memory trend over recent invocations
aws logs filter-log-events \
--log-group-name /aws/lambda/my-function \
--filter-pattern "REPORT" \
--start-time $(date -d '30 minutes ago' +%s000 2>/dev/null || date -v-30M +%s000) \
--query 'events[*].message' \
--output text | grep -oP 'Max Memory Used: \K[0-9]+ MB'
If the values increase steadily (e.g., 85 MB, 102 MB, 119 MB, 127 MB, then killed), you have a memory leak. Move accumulation logic inside the handler function or clear global caches between invocations.
Step 7: Reduce Cold Start Latency (If Timeout Happens on First Invocation)
# Enable Provisioned Concurrency to eliminate cold starts
aws lambda put-provisioned-concurrency-config \
--function-name my-function \
--qualifier prod \
--provisioned-concurrent-executions 5
Provisioned Concurrency keeps execution environments warm so the initialization phase is pre-completed. This costs money, so use it only for latency-sensitive functions.
Is This Safe?
Yes. Increasing memory and timeout values does not affect other functions or services. Lambda pricing is per-invocation based on duration and memory, so higher memory may actually reduce cost if it cuts duration. Provisioned Concurrency adds a fixed cost but is safe to enable and disable at any time.
Key Takeaway
Lambda timeout and memory errors almost always come down to under-provisioned resources or missing timeouts on downstream calls. Check the REPORT line in CloudWatch Logs to distinguish between memory pressure and timeout issues, increase memory (which also increases CPU), set explicit timeouts on every SDK and HTTP client call, and use Lambda Power Tuning to find the configuration that balances cost and performance.
Have questions or ran into a different Lambda issue? Connect with me on LinkedIn or X.