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: Increase maxDuration 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

  • [Vercel Serverless Functions Documentation](https://vercel.com/docs/concepts/functions/serverless-functions)
  • [maxDuration Configuration Reference](https://vercel.com/docs/concepts/functions/serverless-functions/runtimes#max-duration)
  • ---

    Found a different variation? Drop it in the comments below—especially if you hit this with specific frameworks or databases.

    🔥 0d
    LIVE
    ↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising •↑ Resend loved by devs •↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising
    DEVELOPER PAIN RADAR // Loading...

    Developers complain.
    Opportunities appear.

    We track what developers are struggling with today — and what opportunities that creates.

    —
    guides today
    —
    avg happiness
    🔥 Pain
    📖 Guides
    🔭 Explore
    👤 Mine
    🔥 Pain Radar — rage scores today
    ↗ share
    💡 Opportunity Feed — pain = market gap
    📈 Tool Momentum
    all scores →
    📖 Latest Guide
    all guides →
    📖 All Guides
    📊 Tool Scores
    + Submit
    📰 Hacker News
    ➕ Submit a Tool
    ← back