AWS Lambda 'Task Timed Out' and API Gateway 502/504: Fix

Lambda logs 'Task timed out after 3.00 seconds' and your API returns 502 or 504? Find the slow step, check VPC networking, and set timeouts that fit API Gateway.

"Task timed out after 3.00 seconds" is not a crash. Lambda stopped your function because it ran past its configured timeout, which defaults to 3 seconds. Find the step that is slow (usually a database or an outside API call), check that a function inside a VPC can reach the internet, set a timeout that fits the real work, and move long work out of the request path.

Behind API Gateway the same problem looks different to the user. Depending on how the timeout happens, they see a 502 or a 504. This guide shows how to read the logs, find the slow call, and fix it in a sensible order.

Step 1: Read the Log Line and Tell 502 from 504

Open CloudWatch Logs for the function and search for Task timed out. The full line looks like this:

2026-11-07T10:12:03.221Z 4f2c... Task timed out after 3.00 seconds

The number is your configured timeout, not how long the work needs. Next, check the status the client got.

  • 502 Bad Gateway with a Lambda proxy integration. A test published by Classmethod found that a Lambda timeout came back to the client as a 502, because the function never returned a valid response.
  • 504 Gateway Timeout. API Gateway has its own integration limit. StackHarbor notes the default is 29 seconds, so a function allowed to run for 60 seconds still fails for the client at 29. Check the current limits in the AWS docs, since quotas change.

The sources do not fully agree on every case, so verify in your own logs. Compare the request time in API Gateway access logs with the Duration in the Lambda REPORT line.

Step 2: Look at the REPORT Line

Each invocation ends with a REPORT line:

REPORT RequestId: 4f2c...  Duration: 3000.00 ms  Billed Duration: 3000 ms  Memory Size: 128 MB  Max Memory Used: 96 MB  Init Duration: 812.45 ms

Read three things:

  • Duration close to your timeout on every request means the work is too slow or stuck.
  • A large Init Duration is a cold start. Heavy imports and big bundles make it worse.
  • Max Memory Used near Memory Size means memory is tight. Lambda gives CPU in proportion to memory, so a small memory size also means a slow function.

In CloudWatch Logs Insights you can see how widespread it is:

filter @type = "REPORT"
| stats count() as calls, avg(@duration) as avg_ms, max(@duration) as max_ms by bin(5m)

If only a few calls are slow, suspect one dependency. If all are slow, suspect memory or code.

Step 3: Check VPC Networking First

If the function runs inside a VPC, it has no internet access by default. Calls to a payment API, an LLM API or even AWS services will hang until the timeout, with no error in between. StackHarbor lists this as a top cause.

Fix it one of two ways:

  1. Put the function in private subnets whose route table sends 0.0.0.0/0 to a NAT gateway.
  2. Add VPC endpoints for the AWS services you call (S3 and DynamoDB gateway endpoints, interface endpoints for others).

Only attach the function to a VPC if it really needs a private resource such as an RDS database. A function that only calls public APIs runs better outside the VPC.

Step 4: Add Timing Around Every Outside Call

Do not guess which call is slow. Log how long each one takes. A small helper in Node.js:

async function timed(label, fn) {
  const start = Date.now();
  try {
    return await fn();
  } finally {
    console.log(JSON.stringify({ label, ms: Date.now() - start }));
  }
}

export const handler = async (event) => {
  const user = await timed("db.getUser", () => getUser(event.userId));
  const result = await timed("payments.charge", () => charge(user));
  return { statusCode: 200, body: JSON.stringify(result) };
};

Run a few requests and search the logs for the label with the largest ms. Often it is one database query without an index, or a call to a third-party API that sometimes takes 10 seconds.

Step 5: Set Timeouts Inside the Function

If an outside call hangs, your function should give up before Lambda does, so you can return a clean error and log the cause. Use the remaining time from the context:

export const handler = async (event, context) => {
  const budget = context.getRemainingTimeInMillis() - 500;
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), budget);
  try {
    const res = await fetch("https://api.example.com/data", { signal: controller.signal });
    return { statusCode: 200, body: await res.text() };
  } catch (err) {
    console.error("upstream failed", err.name);
    return { statusCode: 504, body: JSON.stringify({ error: "upstream timeout" }) };
  } finally {
    clearTimeout(timer);
  }
};

This turns a silent Lambda kill into a logged error with a proper status code. For retry patterns that work, see API Timeout Errors in Node.js: Retries That Work.

Step 6: Fix Database Connections

Lambda scales by running many copies at once. If each copy opens its own database connection, the database runs out of connections and new calls wait until they time out.

  • Create the client outside the handler so warm invocations reuse it.
  • Use a small pool size, often 1 per function copy.
  • Put a pooler such as RDS Proxy or PgBouncer in front of the database.

The Database Connection Pool Exhaustion guide covers the numbers and symptoms.

Step 7: Set the Timeout and Memory on Purpose

After you know the real time, set the timeout with a margin. For an API behind API Gateway, keep it under the gateway limit so the function fails first with your own error.

aws lambda update-function-configuration \
  --function-name my-api \
  --timeout 20 \
  --memory-size 512

Raising memory also raises CPU, so a function that is CPU bound can get faster and sometimes cheaper. Do not set the timeout to the maximum as a fix. It hides the slow call and makes users wait longer before they see an error.

For work that cannot finish in 29 seconds, such as report exports or image processing, return at once and process it in the background. Put a message on SQS, return 202 Accepted with a job id, and let the client poll or receive a notification. On Vercel the same pattern applies, see Vercel FUNCTION_INVOCATION_TIMEOUT.

How Relia Helps

Lambda timeouts reach users as errors, and the log line does not say who was hit. Relia watches the users, APIs, database and servers of a live product and joins related signals, such as a slow query, a failing request and users seeing an error, into one incident explained in plain words, with who was affected. Node.js apps can start with npx relia-sdk@latest init, and edge and serverless functions are supported. Uptime checks on key endpoints tell you when the API starts returning 502. There is a Free plan, and a live demo at app.tryrelia.com/demo.

FAQ

What is the default Lambda timeout?

Three seconds. You can raise it in the function configuration, up to the Lambda maximum listed in the AWS docs.

Why does API Gateway return 502 when my Lambda times out?

The function did not return a valid response, so API Gateway reports a bad gateway. A 504 means the gateway's own integration timeout was reached first.

Does increasing Lambda memory fix timeouts?

Sometimes. More memory gives more CPU, which helps CPU-bound code and large imports. It does not help if the function waits on a blocked network call.

Why does my Lambda only time out on the first request?

That is a cold start. Reduce bundle size, trim imports, and check Init Duration in the REPORT line.

Sources: OneUptime: Fix Lambda Task Timed Out errors, StackHarbor: Lambda task timed out, DevOpsBoys: AWS Lambda Timeout Error, Classmethod: Lambda proxy timeout response.

All guides