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 in vercel.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

  • [Vercel Functions Documentation](https://vercel.com/docs/functions/introduction)
  • [Timeout Configuration Guide](https://vercel.com/docs/functions/configuring-functions)
  • [Related: Database Connection Timeouts](/?guide=database-timeouts)
  • ---

    Checklist Before Deployment

  • [ ] Set maxDuration in vercel.json (test with 30s first)
  • [ ] Database queries return in <5 seconds (use EXPLAIN ANALYZE)
  • [ ] External API calls have 3-second timeout fallback
  • [ ] No N+1 queries (load related data in single query)
  • [ ] Response size <6MB uncompressed
  • ---

    Found a different variation? Drop it in the comments below — include your error message and what fixed it for you.

    🔥 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