Vercel: 504 timeout on serverless functions [2026 fix]

Serverless functions exceed 10s execution limit or memory threshold. Optimize code, increase timeout, or split into smaller functions.

Vercel: 504 timeout on serverless functions [2026 fix]

TL;DR

Cause: Your serverless function exceeds Vercel's 10-second execution timeout (Pro plan) or 60-second limit (Enterprise), or hits memory constraints during execution. Fix: Optimize database queries, implement caching, reduce payload size, or migrate long-running tasks to background jobs using Vercel Cron or external workers.

---

Real Console Error Messages

Here are exact errors you'll see in Vercel logs:

``` 504: DEADLINE_EXCEEDED FunctionName: api/process-data Duration: 10245ms Error: The function execution time has exceeded the timeout. ```

``` ERROR [api/export-report]: Task timed out after 10000ms Invocation failed: Gateway timeout Request ID: fnc_abc123xyz789 ```

``` {"errorCode":"FUNCTION_TIMEOUT","message":"Serverless function timed out","duration":"10s","maxDuration":"10s","functionName":"api/process-large-dataset"} ```

``` aws_lambda_runtime.api.InvocationError: Task timed out after 10000 milliseconds Stack trace from execution: at Timeout._onTimeout [as _callback] ```

``` Error: ECONNRESET at TCPConnectWrap.afterConnect [as oncomplete] Hangup detected: Function did not respond within 10000ms ```

---

Broken Code vs. Fixed Code

Problem 1: Synchronous Database Loop (BROKEN)

```javascript // ❌ BROKEN - Queries database 1000 times sequentially export default async function handler(req, res) { const userIds = req.body.ids; // array of 1000 IDs let results = []; for (let id of userIds) { // Each query takes ~10ms, total = 10 seconds const user = await db.query(SELECT * FROM users WHERE id = ${id}); results.push(user); } res.json(results); } ```

FIXED: Batch Queries with Connection Pooling

```javascript // ✅ FIXED - Batches queries, uses pooling, completes in ~200ms export default async function handler(req, res) { const userIds = req.body.ids; // Use parameterized batch query const results = await db.query( SELECT * FROM users WHERE id = ANY($1), [userIds] ); res.json(results); } ```

---

Problem 2: Missing Response Timeout (BROKEN)

```javascript // ❌ BROKEN - External API never responds, hangs forever export default async function handler(req, res) { const response = await fetch('https://external-api.com/data'); const data = await response.json(); res.json(data); } ```

FIXED: Add Explicit Timeout

```javascript // ✅ FIXED - Timeout after 5 seconds export default async function handler(req, res) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); try { const response = await fetch('https://external-api.com/data', { signal: controller.signal, timeout: 5000 }); clearTimeout(timeoutId); const data = await response.json(); res.json(data); } catch (error) { res.status(504).json({ error: 'Upstream timeout' }); } } ```

---

Problem 3: Processing Large Files Synchronously (BROKEN)

```javascript // ❌ BROKEN - Loads entire 50MB file into memory export default async function handler(req, res) { const file = await fs.readFile('/tmp/large-export.csv', 'utf-8'); const lines = file.split('\n'); const processed = lines.map(line => expensiveTransform(line)); res.json(processed); } ```

FIXED: Stream Processing

```javascript // ✅ FIXED - Streams file, processes chunks export default async function handler(req, res) { const stream = fs.createReadStream('/tmp/large-export.csv'); const results = []; return new Promise((resolve) => { stream.on('data', chunk => { results.push(expensiveTransform(chunk)); }); stream.on('end', () => { res.json(results); resolve(); }); }); } ```

---

Configuration: Vercel.json Timeout Setting

Note on version behavior: As of 2026, Vercel's timeout limits depend on your plan. Pro plans receive 10 seconds; Enterprise can negotiate. We cannot definitively state if future plans will extend this—check official docs for your tier.

```json { "functions": { "api/long-process.js": { "maxDuration": 60 } } } ```

⚠️ Caveat: Pro plan functions cannot exceed 10s regardless of maxDuration setting. Only Enterprise deployments honor longer values.

---

Still broken? Check these too

1. Cold Start Overhead – First invocation takes 2-3s. Add [HTTP keep-alive](/?guide=vercel-cold-starts) to reduce initial delays. Verify in Vercel dashboard Duration vs. Init Duration metrics.

2. Database Connection Limits – Each function spawn creates new connections. Implement [connection pooling](/?guide=database-pooling) with PgBouncer or similar.

3. Memory Exhaustion – Functions default to 1GB RAM. Monitor via console.log(process.memoryUsage()). Offload to background jobs using Vercel Cron or Bull queue.

---

Official Resources

  • [Vercel Serverless Function Limits](https://vercel.com/docs/concepts/limits/overview)
  • [Vercel Edge Functions](https://vercel.com/docs/concepts/edge-functions/overview) (alternative for <50ms latency)
  • ---

    Found a different variation? Drop it in the comments—we'll add it to this guide.

    🔥 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