Vercel: 504 timeout on serverless functions [2026 fix]
Serverless function exceeds 10s timeout or cold starts fail. Increase function timeout, optimize code, or split into smaller functions.
Vercel: 504 timeout on serverless functions [2026 fix]
TL;DR
Cause: Your serverless function exceeded Vercel's execution timeout (10 seconds default) or failed during cold start initialization. Fix: Increase timeout invercel.json, optimize database queries, or migrate heavy processing to background jobs.---
Real Console Error Messages
Here are exact error outputs you'll see:
``` 504 Gateway Timeout The request took too long to process and was terminated. Request ID: abc123def456 Duration: > 10000ms ```
``` [ERROR] RequestId: xyz789abc123 Task timed out after 10.01 seconds FATAL Error: Lambda execution timeout exceeded ```
``` 504 Service Unavailable Upstream request timeout Vercel Function Error: FUNCTION_INVOCATION_TIMEOUT Elapsed: 10012ms ```
``` ERROR Function crashed Timeout waiting for function to respond Status: 504 Duration exceeded: 10 seconds ```
``` Cannot GET /api/process Error: The function execution has timed out (10s). Trace: at FunctionTimeout (runtime) ```
---
The Problem (Broken Code)
```javascript // ❌ BROKEN: Database query takes 15+ seconds export default async function handler(req, res) { try { // Unoptimized query with 3 nested joins const result = await db.query(` SELECT users.*, orders.*, products.* FROM users JOIN orders ON users.id = orders.user_id JOIN products ON orders.product_id = products.id WHERE users.status = 'active' `); // Processing takes 8+ seconds const processed = result.map(item => { return heavyCalculation(item); // CPU-intensive }); res.status(200).json(processed); } catch (err) { res.status(500).json({ error: err.message }); } } ```
---
The Fix (Side by Side)
Fix #1: Increase Timeout + Optimize Query
Step 1: Update vercel.json
```json { "functions": { "api/process.js": { "maxDuration": 30 } } } ```
Step 2: Optimize the function
```javascript // ✅ FIXED: Paginated query + indexed fields export default async function handler(req, res) { res.setHeader('Content-Type', 'application/json'); try { // Use pagination to limit dataset const page = parseInt(req.query.page) || 1; const limit = 50; const offset = (page - 1) * limit; // Only select needed fields const result = await db.query(` SELECT users.id, users.name, orders.total FROM users JOIN orders ON users.id = orders.user_id WHERE users.status = $1 LIMIT $2 OFFSET $3 `, ['active', limit, offset]); // Process in batches or move to background job const processed = await Promise.all( result.map(item => cachedHeavyCalculation(item)) ); res.status(200).json({ data: processed, page, hasMore: processed.length === limit }); } catch (err) { console.error('Function error:', err); res.status(500).json({ error: 'Processing failed' }); } } ```
Fix #2: Move Heavy Work to Background Job
```javascript // ✅ FIXED: Return immediately, process async import { queue } from '@vercel/functions';
export default async function handler(req, res) { try { const jobId = crypto.randomUUID(); // Queue task instead of processing inline await queue.enqueue({ name: 'heavy-processing', jobId, data: req.body }); // Return immediately res.status(202).json({ message: 'Processing started', jobId }); } catch (err) { res.status(500).json({ error: err.message }); } } ```
Fix #3: Add Connection Pooling
```javascript // ✅ FIXED: Reuse database connections import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 20, idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000 });
export default async function handler(req, res) { const client = await pool.connect(); try { const result = await client.query('SELECT ...'); res.status(200).json(result.rows); } finally { client.release(); } } ```
---
Still broken? Check these too
1. Cold Start Issues — New functions load slowly. Enable [Vercel's prerender option](/?guide=vercel-cold-starts) or keep functions warm with scheduled requests.
2. Memory Constraints — Functions limited to 512MB-3008MB depending on plan. Check memory usage with console.time() and optimize large data processing.
3. Environment Variables Loading — Slow secret retrieval can timeout. Verify DATABASE_URL and credentials load within 1 second using console.time('env-load').
---
Official Resources
---
Checklist Before Deployment
maxDuration in vercel.json (test with 30s first)---
Found a different variation? Drop it in the comments below — include your error message and what fixed it for you.