Task timed out after 3.00 seconds is not a crash — it is Lambda enforcing the timeout configured on the function, and the default is a very short 3 seconds. The fix is almost never “raise the timeout to 900 and move on.” The fix is finding out where the time went: a downstream call that hangs, a VPC configuration that black-holes outbound traffic, heavy initialization inside the handler, or a function that is genuinely CPU-starved at its current memory setting. Raise the timeout only once you know which one it is.
What’s happening
Every Lambda function has a timeout between 1 second and 900 seconds (15 minutes). When the handler is still running at the deadline, Lambda kills the execution environment mid-flight and writes Task timed out after N seconds to the log stream. No cleanup code runs, no exception is catchable, and for asynchronous invocations Lambda will retry the event up to two more times — so a timing-out function often does its damage two or three times.
The time usually goes to one of four places. First, a downstream dependency: an HTTP call, an RDS query, or an SDK call with no client-side timeout will happily wait longer than the function is allowed to live. Second, networking: a function attached to a VPC without a working egress path does not get a connection refused — packets leave and nothing comes back, so the socket waits until Lambda pulls the plug. Third, initialization: loading a heavy framework or fetching configuration inside the handler instead of in the init phase adds seconds to every invocation. Fourth, actual compute: Lambda allocates CPU in proportion to memory, so a 128 MB function gets a small slice of a vCPU and CPU-bound work crawls.
One boundary matters even if the function itself is fine: API Gateway’s default integration timeout is 29 seconds. A synchronous function behind API Gateway that runs 40 seconds returns a 504 to the client even though Lambda is happy — the two timeouts have to be designed together.
What to check first
- The configured timeout. If it is still the 3-second default, nobody ever sized it — that alone explains intermittent timeouts on cold starts or slow dependencies.
- The REPORT line. Every invocation ends with
REPORT RequestId: ... Duration: ... Billed Duration: ... Max Memory Used: .... Timeouts show a Duration nearly equal to the timeout, which tells you the function ran out of road rather than finishing slowly. - Whether the function is in a VPC. VPC plus timeout plus “it worked before we attached it to the VPC” is an egress problem until proven otherwise.
- Whether it only happens on cold starts. Check for an
Init Durationfield on the failing invocations — a pattern of timeouts only when init ran points at expensive startup code. - Downstream health. If timeouts started at 14:02 and your database or a third-party API had trouble at 14:02, the function is the victim, not the culprit.
How to verify
Get the current configuration:
aws lambda get-function-configuration \
--function-name my-function \
--query '{Timeout: Timeout, Memory: MemorySize, VPC: VpcConfig.VpcId}'
In the console, Lambda > Functions > (function) > Configuration > General configuration shows timeout and memory; the Monitor tab shows Duration and Errors together, and timeouts appear as errors.
In CloudWatch Logs Insights against the function’s log group:
filter @message like /Task timed out/
| stats count() by bin(15m)
Then look at the shape of durations to see whether the whole population is slow or only a tail:
filter @type = "REPORT"
| stats avg(@duration), pct(@duration, 95), max(@duration), max(@initDuration) by bin(15m)
If p95 sits at 800 ms and only max hits the timeout, you have a hanging dependency in the tail. If the whole distribution has drifted up, the workload changed. Details of the lifecycle and the REPORT fields are in the Lambda documentation at https://docs.aws.amazon.com/lambda/.
The fix
- Put client timeouts on every downstream call. The most common real cause. Configure the HTTP client and database driver with connect and read timeouts that sum to comfortably less than the function timeout, so the function fails fast with a real error message instead of dying silently at the deadline.
- Fix VPC egress if the function is attached to a VPC. A Lambda function needs a private subnet whose route table points at a NAT gateway to reach the internet, or VPC endpoints for AWS services — a public subnet does not work because the function’s ENI never gets a public IP. The trade-offs are covered in NAT gateway vs NAT instance.
- Move one-time work into the init phase. Create SDK clients, database connection objects, and configuration reads outside the handler so they run once per execution environment instead of once per invocation.
- Raise memory if the work is CPU-bound. More memory means proportionally more CPU. A function doing JSON parsing, compression, or crypto at 128 MB is often both faster and cheaper at 512 MB or 1024 MB because billed duration drops.
- Then, and only then, set a deliberate timeout. Pick roughly 2-3x the observed p99 duration. For synchronous APIs behind API Gateway, keep the function timeout under the 29-second integration limit unless you have specifically raised that quota.
- Restructure work that legitimately needs more than 15 minutes. Chunk it behind SQS, or orchestrate it with Step Functions — a single Lambda invocation is the wrong unit for long jobs.
When this is the wrong move
If the function talks to RDS and timeouts cluster with connection errors, the real problem may be connection exhaustion on the database side — that is a pooling problem, and RDS Proxy is the fix, not a longer timeout. And if a batch job keeps flirting with the 15-minute ceiling, do not shave it under the limit with bigger memory — move it to ECS, Fargate, or Step Functions where the ceiling does not exist.
Common mistakes
- Setting the timeout to 900 seconds “to be safe” — a hanging invocation now burns 15 minutes of billed duration per retry and hides the underlying fault.
- Forgetting that async invocations retry twice by default, so a timing-out function may execute side effects three times.
- Blaming Lambda when API Gateway’s 29-second integration timeout is what actually cut the request.
- Testing with warm invocations only, then shipping and discovering cold-start init pushes real traffic over the deadline.
Prevention
- Alarm on the function’s
ErrorsandDurationmetrics, with the duration threshold at ~80% of the timeout so you see drift before customers do. - Log the elapsed time of each downstream call so a future timeout tells you which hop ate the budget.
- Set explicit timeouts in every SDK and HTTP client as a code-review rule.
- Re-run a duration percentile query after every dependency or traffic change; timeouts are usually a slow drift, not a sudden break.
Timeouts are the symptom Lambda gives you when any part of the request path stops answering, which makes them a decent early-warning system if someone is actually reading them. If nobody on your team truly owns the AWS environment end to end, that is the root of most of these problems — Stack Harbor runs AWS accounts daily under AWS Operations, and you can book an AWS review.