API Gateway Integration Timeout: Fix in 30s, 5min, or 15min
Your API Gateway keeps timing out on integrations? Here's how to diagnose and fix it — from a simple timeout bump to a full async re-architecture.
What's Actually Happening Here
API Gateway has a hard 29-second limit for integration timeouts. That's not a configurable slider — it's the absolute max. If your backend (Lambda, HTTP endpoint, or VPC Link) doesn't respond within that window, you get a 504. The real question is: why is your backend slow? That's what we'll fix.
I've seen this most often with a Lambda that starts a cold container (6–10 seconds on Python, up to 15 on Java) plus a heavy database query. Or an HTTP integration behind a VPC Link that's hitting a network hop with high latency. Let's work through the fix layers.
Level 1: 30-Second Fix — Bump the Timeout (If You Haven't Already)
This sounds dumb, but you'd be surprised how many people leave the default 5-second timeout. Open your API Gateway console, find the integration, and set the timeout to 29000 ms (29 seconds).
- Go to API Gateway → your API → Resources → select the method (GET, POST, etc.)
- Click Integration Request
- Under Timeout, enter
29000(milliseconds) - Deploy the API change
Test again. If the 504 goes away, you're done. But here's the catch: if your backend genuinely takes longer than 29 seconds, this won't help. You'll just get a 504 at 29 seconds instead of 5. That means your backend is too slow for a synchronous API call — see Level 3.
Level 2: 5-Minute Fix — Optimise the Backend
If the 504 persists, your backend is the bottleneck. Let's find and fix it.
Lambda Integration
Check Lambda's CloudWatch logs for timeout errors. If your Lambda's configured timeout is higher than API Gateway's 29 seconds, you'll see Task timed out after X seconds in the logs. Reduce the Lambda's timeout to match API Gateway's 29 seconds — no point waiting longer.
Real fix: enable Provisioned Concurrency on your Lambda to kill cold starts. That shaves off 5–15 seconds. Set it to 1–5 provisioned instances depending on traffic. Cost is negligible for a low-volume API.
aws lambda put-provisioned-concurrency-config --function-name your-function --qualifier prod --provisioned-concurrent-executions 2
Deploy and test. If the 504 stops, great. If not, look at the Lambda's database calls. Are you running a slow query? Use AWS X-Ray to trace where time is lost. I once found a 20-second Postgres query due to a missing index. Adding the index dropped response time to 200ms.
HTTP / VPC Link Integration
VPC Link timeouts are trickier because the timeout includes network latency plus your backend's processing. Check the following:
- NAT Gateway: if your VPC Link goes through a NAT Gateway, you pay for each connection and it adds latency. Move to a VPC Endpoint (PrivateLink) for direct connection.
- Backend health: hit the backend directly from an EC2 instance in the same VPC. If it responds fast, the issue is the VPC Link's path — maybe a misconfigured NLB or target group.
- Target group timeout: your NLB's target group has its own timeout. Default is 350 seconds. If it's lower than 29 seconds, raise it.
Level 3: 15+ Minute Fix — Async Pattern (When 29 Seconds Isn't Enough)
Sometimes your backend genuinely takes 30+ seconds — a PDF generation, a heavy data export, or a third-party API that's slow as molasses. You can't fix that by tuning. You need to change the architecture.
The pattern: API Gateway accepts the request, returns a 202 Accepted immediately (with a unique request ID), and your backend processes asynchronously. The client polls a separate status endpoint until the result is ready.
How to Build It
- API Gateway endpoint: POST /submit — Lambda receives the request, stores it in DynamoDB with status 'processing', and returns 202 with the request ID.
- Background processing: That Lambda (or a separate one triggered by SQS or EventBridge) does the heavy work. It writes the result back to DynamoDB and updates status to 'complete'.
- Status polling: GET /status/{requestId} — Lambda looks up the item in DynamoDB and returns the result if status is 'complete'.
This bypasses the 29-second timeout entirely because the initial Lambda returns in under 50ms. The heavy work happens outside of API Gateway's timeout window.
Why this matters: I've seen teams try to hack around the timeout by retrying with exponential backoff — that just increases your AWS bill and frustrates clients. Embrace async. It's cleaner, scales better, and you can give real progress updates.
When to Throw in the Towel
If you're still getting 504s after all three levels, double-check you're not hitting a regional API Gateway with a private API over a VPC Endpoint. Private APIs have a different timeout behavior — they can't use custom domain names without additional setup. But that's a different error.
Also, verify that your backend isn't crashing with a 500 before the timeout. A 504 specifically means API Gateway didn't get a response in time. If you see 500s in the logs, that's a different fix — check your backend code.
One last thing: if you're using WebSocket API Gateway, the timeout is different. This guide is for REST and HTTP APIs.
Quick Cheat Sheet
| Symptom | Fix | Time |
|---|---|---|
| 504 on first request only | Enable Lambda provisioned concurrency | 5 min |
| 504 on every request, backend takes 10–28s | Optimize backend code or database | 5 min |
| 504 on every request, backend takes 30+ s | Switch to async processing | 15+ min |
| 504 with VPC Link | Check NLB target group timeout | 5 min |
| 504 after scaling | Check Concurrency limits in Lambda | 5 min |
Was this solution helpful?