Vercel: 504 timeout on serverless functions [2026 fix]
Serverless function exceeds 10s timeout or cold start memory spike. Increase function timeout, optimize initialization code, and enable streaming responses.
Vercel: 504 timeout on serverless functions [2026 fix]
TL;DR
Cause: Your serverless function exceeds Vercel's 10-second default timeout or runs out of memory during cold starts. Fix: SetmaxDuration in vercel.json, optimize imports outside request handlers, and use streaming for long operations.---
Exact Error Messages from Console
``` Error: FUNCTION_INVOCATION_TIMEOUT The Serverless Function exceeded the 10s timeout specified. Please check that your code completes. ```
``` ERROR: 504 Gateway Timeout The server did not respond within the specified time period. ```
``` WARN: Cold Start took 8234ms Function duration: 5000ms Total: 13234ms (exceeded 10000ms limit) ```
``` Error: Task timed out after 900 seconds RESET /api/export - 504 ```
``` FATAL ERROR: CALL_SNAPSHOT_FAILURE Unable to restore function snapshot within timeout window. ```
---
Code: Before vs. After
❌ BROKEN CODE
api/export.js (slow import + no timeout config) ```javascript // ❌ Importing heavy libraries at module level const pdf = require('pdfkit'); const sharp = require('sharp'); const crypto = require('crypto');
export default async function handler(req, res) { // Process takes 15+ seconds const document = new pdf.PDFDocument(); for (let i = 0; i < 1000; i++) { const processed = await sharp(imageBuffer) .resize(800, 600) .toBuffer(); document.image(processed); } res.setHeader('Content-Type', 'application/pdf'); res.send(document); } ```
vercel.json (missing timeout config) ```json { "version": 2, "builds": [{"src": "api/**/*.js", "use": "@vercel/node"}] } ```
---
✅ FIXED CODE
api/export.js (lazy imports + streaming) ```javascript // ✅ Import heavy libraries INSIDE handler to delay cold start export default async function handler(req, res) { const pdf = require('pdfkit'); const sharp = require('sharp'); // ✅ Set response headers for streaming res.setHeader('Content-Type', 'application/pdf'); const document = new pdf.PDFDocument(); document.pipe(res); // ✅ Process in smaller batches to avoid memory spike for (let i = 0; i < 1000; i++) { if (i % 100 === 0) { // Yield to event loop every 100 items await new Promise(resolve => setImmediate(resolve)); } const processed = await sharp(imageBuffer) .resize(800, 600) .toBuffer(); document.image(processed); } document.end(); } ```
vercel.json (timeout + memory config) ```json { "version": 2, "functions": { "api/export.js": { "maxDuration": 60, "memory": 3008 } }, "builds": [{"src": "api/**/*.js", "use": "@vercel/node"}] } ```
---
Why This Works
1. maxDuration: 60 – Extends timeout from default 10s to 60s (Pro plans support up to 900s; we're uncertain if this changed in 2026, check official docs).
2. Lazy imports – Moving require() inside handlers delays library loading, reducing cold start time counted against your timeout window.
3. Streaming response – Using .pipe(res) sends data progressively instead of buffering the entire PDF in memory.
4. memory: 3008 – Allocates maximum memory (3GB on Pro) to prevent out-of-memory kills during processing.
5. Event loop yields – setImmediate() prevents V8 from blocking on large loops, letting Node.js handle other operations.
---
Still broken? Check these too
1. Database Query Timeouts
If your API calls a database, add explicit query timeouts: ```javascript const result = await db.query(sql, { timeout: 5000 }); // 5s per query ``` See [database connection pooling guide](/?guide=database-timeouts) for details.2. External API Calls Hanging
Third-party APIs may not respond quickly. Add fetch timeouts: ```javascript const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 8000); const res = await fetch(url, { signal: controller.signal }); ``` Related: [external API integration patterns](/?guide=api-calls).3. Memory Leaks in Loops
Declare variables inside loops to prevent accumulation: ```javascript for (let i = 0; i < items.length; i++) { const item = items[i]; // ✅ New scope per iteration // ... process item } ```---
Official Resources
---
Quick Checklist
maxDuration to vercel.jsonrequire() statements inside handlers---
Found a different variation? Drop it in the comments—we update this guide based on real production incidents.