Fix AWS Lambda "Task timed out after 3.00 seconds" Error

intermediateโ˜๏ธ AWS2026-03-17| AWS Lambda (any runtime: Node.js, Python, Java, Go) โ€” AWS Console / AWS CLI / Serverless Framework

Error Message

Task timed out after 3.00 seconds
#aws#lambda#timeout#function

The Error

Your Lambda function logs show:

Task timed out after 3.00 seconds

Lambda killed the function before it finished. That default 3-second timeout works fine for a hello-world function. Add one HTTP call to a third-party API or a database query under load, and 3 seconds evaporates fast.

Root Causes

  • Default timeout too short โ€” Lambda ships with a 3-second default. A single slow API call blows past that before you know it.
  • External network calls โ€” HTTP requests to third-party APIs, RDS, or DynamoDB can take 1โ€“5 seconds under load, sometimes longer.
  • Cold start latency โ€” JVM-based runtimes (Java, Kotlin) routinely add 800msโ€“2s before your code even starts. Large Python packages can tack on another 200โ€“400ms.
  • Infinite loops or blocking waits โ€” A polling loop that never exits, or a time.sleep(10) buried somewhere in the call stack.
  • VPC networking โ€” Functions inside a VPC have slower cold starts and will hang on external calls if there's no NAT Gateway configured.

Step 1 โ€” Check the Logs First

Don't touch any config yet. Pull up CloudWatch Logs to see where the time is actually going.

# Tail logs via AWS CLI
aws logs tail /aws/lambda/your-function-name --follow

# Or filter for REPORT lines which show duration
aws logs filter-log-events \
  --log-group-name /aws/lambda/your-function-name \
  --filter-pattern "REPORT" \
  --query 'events[*].message' \
  --output text

The REPORT line tells you everything you need:

REPORT RequestId: abc-123  Duration: 2987.43 ms  Billed Duration: 2988 ms  Memory Size: 128 MB  Max Memory Used: 67 MB  Init Duration: 412.31 ms

Init Duration above 400ms points to a cold start problem. Duration close to your timeout limit means the function itself is genuinely slow โ€” and raising the limit is the right move.

Step 2 โ€” Increase the Timeout

Bump the timeout first. The max is 15 minutes (900 seconds).

Via AWS Console

  • Go to Lambda โ†’ Your function โ†’ Configuration โ†’ General configuration
  • Click Edit
  • Set Timeout to something realistic โ€” 30 seconds is a sensible starting point for functions that make external calls
  • Click Save

Via AWS CLI

aws lambda update-function-configuration \
  --function-name your-function-name \
  --timeout 30

Via Serverless Framework (serverless.yml)

functions:
  myFunction:
    handler: handler.main
    timeout: 30  # seconds

Via Terraform

resource "aws_lambda_function" "my_function" {
  function_name = "my-function"
  timeout       = 30
  # ... other config
}

A good rule of thumb: set the timeout to 2โ€“3ร— your expected worst-case duration. Resist the urge to just slam it to 900 โ€” you'll hide real performance regressions that way.

Step 3 โ€” Add Timing Logs to Find the Bottleneck

Still timing out at 30s? Instrument the code so the logs tell you exactly which step is eating the time.

Python

import time
import logging

logger = logging.getLogger()

def handler(event, context):
    t0 = time.time()
    
    result = fetch_from_database()
    logger.info(f"DB query took {time.time() - t0:.2f}s")
    
    t1 = time.time()
    response = call_external_api(result)
    logger.info(f"API call took {time.time() - t1:.2f}s")
    
    return response

Node.js

exports.handler = async (event) => {
  console.time('db-query');
  const result = await fetchFromDatabase();
  console.timeEnd('db-query');

  console.time('api-call');
  const response = await callExternalAPI(result);
  console.timeEnd('api-call');

  return response;
};

Deploy, invoke once, then check CloudWatch. The slow step sticks out immediately.

Step 4 โ€” Optimize the Slow Path

Set explicit timeouts on all HTTP clients

HTTP clients without a timeout will wait forever. Set one on every outbound call โ€” no exceptions.

# Python with requests
import requests
response = requests.get('https://api.example.com/data', timeout=5)  # 5s max

# Python with httpx (async)
async with httpx.AsyncClient(timeout=5.0) as client:
    response = await client.get('https://api.example.com/data')
// Node.js with axios
const axios = require('axios');
const response = await axios.get('https://api.example.com/data', {
  timeout: 5000  // 5s in ms
});

Move SDK client initialization outside the handler

AWS SDK clients created inside the handler get rebuilt on every single invocation. Move them to module level instead. Lambda reuses the execution environment on warm starts, so you pay that setup cost exactly once.

# Bad โ€” creates new client on every invocation
def handler(event, context):
    dynamodb = boto3.client('dynamodb')
    ...

# Good โ€” client initialized once, reused on warm starts
import boto3
dynamodb = boto3.client('dynamodb')

def handler(event, context):
    ...

Increase memory to get more CPU

Lambda CPU scales linearly with memory. Going from 128MB to 512MB gives you 4ร— the CPU. For CPU-bound workloads, that can cut execution time by half or more.

aws lambda update-function-configuration \
  --function-name your-function-name \
  --memory-size 512

Run Lambda Power Tuning to find the memory setting that balances speed against cost for your specific function.

Lambda inside a VPC

Without a NAT Gateway, your function simply cannot reach the internet. External HTTP calls hang until Lambda kills them. Check your subnet's route table โ€” you need a route for 0.0.0.0/0 pointing to a NAT Gateway (a NAT Instance won't cut it).

# Check if function is VPC-attached
aws lambda get-function-configuration \
  --function-name your-function-name \
  --query 'VpcConfig'

Step 5 โ€” Verify the Fix

Invoke the function directly and check the response:

# Synchronous test invocation
aws lambda invoke \
  --function-name your-function-name \
  --payload '{}' \
  --cli-binary-format raw-in-base64-out \
  output.json

cat output.json

Pull up the REPORT line in CloudWatch. Duration well below your timeout setting means you're done:

REPORT RequestId: xyz-456  Duration: 1243.12 ms  Billed Duration: 1244 ms

No Task timed out after 3.00 seconds in the logs. Fixed.

Lessons Learned

  • 3 seconds is Lambda's default, not a recommendation. Most production functions need 15โ€“60 seconds.
  • Set the timeout on every function that makes external calls โ€” and pick the number deliberately, not whatever happened to be there.
  • Java and Kotlin cold starts routinely eat 1โ€“2 seconds before your handler even runs. If that's unacceptable, look at Provisioned Concurrency or SnapStart (Java 11+).
  • Set HTTP client timeouts shorter than your Lambda timeout. That way you get a proper exception you can handle โ€” instead of waiting for Lambda to kill the whole function.

Related Error Notes