Fix guides / Vercel: "504 FUNCTION_INVOCATION_TIMEOUT"
How to fix Vercel "FUNCTION_INVOCATION_TIMEOUT" (504)
Locally the request finishes. On Vercel you get 504: GATEWAY_TIMEOUT with Code: FUNCTION_INVOCATION_TIMEOUT. Vercel stopped your serverless function because it ran past its maximum duration.
Step 1: find out why it is slow
Open the deployment, then Logs, and filter by the failing route. Add timing logs around each external call:
console.time('openai'); const r = await openai.chat.completions.create(...); console.timeEnd('openai');
The usual suspects, in order: a long AI model call, a database query with no index, a request to a third-party API that hangs, and code that forgets to return a response so the function waits until it is killed.
Fix 1: raise the limit (if the work is legitimately long)
In the App Router, export a max duration from the route file:
// app/api/generate/route.ts export const maxDuration = 60; // seconds, within your plan's limit
In the Pages Router or plain functions, set it in vercel.json:
{ "functions": { "api/**/*.ts": { "maxDuration": 60 } } }
Limits depend on your plan and whether Fluid compute is on, so check the current values in the Vercel docs for your plan.
Fix 2: stream AI responses instead of waiting
Streaming sends the first bytes fast and keeps the connection alive. With the AI SDK, return result.toTextStreamResponse() (or the equivalent for your SDK) rather than awaiting the full completion.
Fix 3: always return, and always time out outbound calls
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), 8000);
try {
const res = await fetch(url, { signal: ctrl.signal });
return Response.json(await res.json());
} catch (e) {
return Response.json({ error: 'upstream timeout' }, { status: 504 });
} finally { clearTimeout(t); }
Fix 4: database connections
Serverless functions should use a pooled connection string (Supabase's pooler, Neon's pooled URL, Prisma Accelerate and similar). A direct Postgres connection from every invocation can exhaust connections and leave requests hanging.
Fix 5: move long jobs out of the request
Anything that takes minutes (video, big imports, batches of AI calls) belongs in a background job or queue. Return a job ID right away and let the client poll for the result.
Check the fix
- Redeploy and hit the route on the live URL.
- In Logs, the duration is well under your limit and the status is 200.
Quick Fix, $49Full Rescue, $149Ask first
Last updated 2026-10-19.