Vercel: 504 timeout on serverless functions [2026 fix]
Serverless functions exceed 10s timeout or cold start delay. Increase function timeout, optimize code, or switch to long-running compute.
Vercel: 504 timeout on serverless functions [2026 fix]
TL;DR
Cause: Your serverless function exceeded Vercel's default 10-second timeout or is cold-starting during peak load. Fix: IncreasemaxDuration in vercel.json to 60 seconds, optimize database queries, and implement connection pooling.---
Exact Error Messages
Error 1: Standard 504 Gateway Timeout
``` HTTP/1.1 504 Gateway Timeout Content-Type: application/json{ "error": { "code": "FUNCTION_INVOCATION_TIMEOUT", "message": "Your serverless function exceeded the maximum execution time", "duration": 10000 } } ```
Error 2: CloudFront Timeout
``` HTTP/1.1 504 Gateway Timeout Server: CloudFront X-Amz-Cf-Error-Id: abc123xyz== Content-Length: 571<Error> <Code>GatewayTimeout</Code> <Message>The server did not respond before the timeout period expired.</Message> </Error> ```
Error 3: Logs Output
``` 2024-01-15T02:43:12.156Z ERROR RequestId: id-xyz-123 Task timed out after 10.00 seconds at Runtime.handler (index.js:45:12) at async processRequest (/var/task/node_modules/next/dist/server/lib/utils.js:123:45) ```Error 4: Browser Console
``` Failed to fetch resource: the server responded with a status of 504 () XHR POST https://api.example.com/api/process 504 () ```Error 5: Cold Start Delay
``` Duration: 15234.56 ms (exceeds 10000ms limit) Init Duration: 8954.23 ms Billed Duration: 10000 ms Max Memory Used: 512 MB ```---
Code Comparison: Broken vs Fixed
❌ BROKEN CODE
api/process.js (default timeout)
```javascript
export default async function handler(req, res) {
// No timeout config - defaults to 10 seconds
const data = await fetch('https://slow-api.example.com/endpoint');
const processed = await expensiveCalculation(data);
const dbResult = await db.query('SELECT * FROM large_table');
res.status(200).json({ result: dbResult });
}
async function expensiveCalculation(data) {
// Unoptimized: no batching, no pooling
for (let i = 0; i < 10000; i++) {
await db.query(SELECT * FROM users WHERE id = ${i});
}
}
```
vercel.json (missing configuration)
```json
{
"buildCommand": "next build"
}
```
✅ FIXED CODE
api/process.js (optimized)
```javascript
export default async function handler(req, res) {
try {
// Add timeout abort signal
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 55000); // 55s - leave 5s margin
// Batch database queries instead of looping const ids = Array.from({ length: 10000 }, (_, i) => i + 1); const dbResult = await db.query( 'SELECT * FROM users WHERE id = ANY($1)', [ids] );
// Use connection pooling const data = await fetch('https://slow-api.example.com/endpoint', { signal: controller.signal, timeout: 8000 });
clearTimeout(timeoutId); res.status(200).json({ result: dbResult }); } catch (error) { if (error.name === 'AbortError') { res.status(503).json({ error: 'Request timeout' }); } else { res.status(500).json({ error: error.message }); } } } ```
vercel.json (with timeout configuration)
```json
{
"buildCommand": "next build",
"functions": {
"api/**/*.js": {
"maxDuration": 60,
"memory": 1024
}
}
}
```
Database Connection Setup ```javascript // lib/db.js - Use connection pooling import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 20, idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, });
export default pool; ```
---
Version-Specific Notes
Vercel Functions (2024-2026): maxDuration accepts 10-3600 seconds on Pro/Enterprise plans. Free tier capped at 10 seconds—upgrade if needed.
Next.js 13+: Route handlers (app/api/route.js) and legacy API routes both support maxDuration export.
Node.js version: Confirm your package.json specifies Node 18+. Earlier versions have slower garbage collection.
---
Still broken? Check these too
1. [Database Connection Pooling Failures](/?guide=vercel-connection-pool) – Each cold start creates new DB connection. Use PgBouncer or Prisma Connection Pool.
2. [Memory Limit Reached During Execution](/?guide=vercel-oom-killer) – 512MB default may be insufficient. Increase via memory: 3008 in vercel.json.
3. [External API Timeout Cascades](/?guide=slow-api-calls) – Third-party API hanging blocks your function. Add explicit timeout on fetch() calls.
---
Official Resources
---
Found a different variation? Drop it in the comments below—especially if you hit this with specific frameworks or databases.