DevOps & Cloud

Fixing Vercel Server Function Timeout: A Practical Guide

Learn how to bypass Vercel's default function limits by using Fluid Compute and external triggers to handle long-running background tasks.

By · · 7 min read

Short answer

Vercel Hobby plan functions default to a 10-second limit, while Pro allows up to 60 seconds. To bypass these, use Fluid Compute to extend your maxDuration up to 300 seconds. For processes exceeding 5 minutes, move logic to an external worker and trigger it via a webhook or cron-job.org.

Key takeaways

  • Vercel Hobby and Pro have strict execution limits (10s and 60s respectively) unless you opt-in to Fluid Compute.
  • Setting maxDuration in your route config is the primary way to increase execution windows up to 300 seconds.
  • Vercel functions are not meant for indefinite processing; use waitUntil for post-response cleanup or move heavy tasks to a VPS.
  • Always use a third-party cron service like cron-job.org to prevent HTTP timeouts on long-running jobs.

Why is my Vercel server function timing out?

Vercel serverless functions operate within a constrained environment designed to maximize resource availability for all users. When you deploy a function, Vercel executes your code in an isolated instance that has fixed CPU and memory limits. These infrastructure guardrails protect the platform from rogue scripts or runaway processes that would otherwise consume too many shared resources, causing latency for others.

The standard default timeout behavior is restrictive by design. On the Hobby plan, your functions are capped at 10 seconds of execution time. If you are on the Pro plan, that threshold extends to 60 seconds. These time limits start the moment the HTTP request hits your serverless function and end when the function finishes sending its response back to the client.

When your code performs intensive data processing, waits on slow third-party API responses, or attempts to read/write large files to the filesystem, it consumes time rapidly. If the cumulative execution time crosses your plan's specific limit, Vercel kills the process immediately. The browser or API client that initiated the call receives a 504 Gateway Timeout error, signaling that the server could not complete the operation within the allotted window.

Understanding these boundaries is the first step toward fixing them. If your application logic requires more time than the default, it is likely because you are attempting to complete long-running operations—such as generating a complex PDF or training a small model—within the scope of a single request-response cycle. This architectural pattern often leads to recurring timeouts if left unaddressed.

PlanDefault LimitMax with Fluid Compute
Hobby10s300s
Pro60s300s

How to increase maxDuration for API routes

When you realize your function needs more time to execute, the simplest path forward is to modify your route segment configuration. Next.js allows you to control the execution environment of specific files by exporting a maxDuration constant. This value is measured in seconds and informs the Vercel builder how long it should allow your specific function to live before force-closing it.

By setting maxDuration = 300, you are opting into Fluid Compute. This is a specific Vercel feature that lifts the standard 10s or 60s limit and pushes it up to 5 minutes (300 seconds). This extra time is invaluable for tasks that are just slightly too slow for the default tiers. You simply add this constant at the top level of your API route or Server Action file to apply the change immediately upon your next deployment.

While this approach is straightforward, you should be mindful of the cost implications. Enabling Fluid Compute may alter your billing, especially if your function volume is high on the Hobby plan or if you consume large amounts of compute time. You should treat the usage dashboard as a source of truth to ensure your function usage remains within your budget. Always verify the status of your plan before setting a 300-second limit on high-traffic endpoints.

Be careful not to over-provision. If your logic only needs 15 seconds, setting a 300-second limit does not hurt performance directly, but it does allow runaway loops to consume significantly more resources before being shut down by the system. Only increase this value to the minimum time required to complete your intended task successfully.

export const maxDuration = 300;

export async function POST(request: Request) {
  // Heavy logic goes here
  // This function can now run up to 300 seconds total
  return Response.json({ success: true });
}

Using waitUntil for non-blocking tasks

One common cause of unnecessary timeouts is keeping a user waiting for a response that could have been sent much earlier. Often, your logic performs a series of steps where only the first few are required for the user to see success, while the remaining steps are side effects like logging, sending notification emails, or cleaning up temporary data in a database.

The waitUntil utility provided by @vercel/functions is the solution to this problem. It allows you to define a task that should continue to run even after the main request has been acknowledged. When you wrap your heavy processing in waitUntil, Vercel sends the response to the client immediately and keeps the function context alive in the background to finish the remaining work.

This pattern significantly improves the user experience by reducing the latency perceived by the person triggering the function. The user gets their confirmation in milliseconds, while the heavy lifting—such as processing a report or uploading an image to S3—continues silently behind the scenes until completion or until the maxDuration limit is reached.

It is essential to understand that waitUntil is still subject to your function's overall maxDuration. If you set your limit to 60 seconds and your total task takes 70 seconds, the background work will be terminated exactly at 60 seconds regardless of the waitUntil implementation. Plan your background tasks so they finish well within the window you have configured for your specific route.

import { waitUntil } from '@vercel/functions';

export async function POST(request: Request) {
  waitUntil(
    (async () => {
      // This task runs after the response is sent
      await performHeavyTask();
    })()
  );

  // The client receives this response immediately
  return Response.json({ status: 'Processing' });
}

Handling jobs longer than 5 minutes

If you find that your task consistently requires more than 300 seconds, you have reached the hard ceiling of Vercel Serverless Functions. At this stage, trying to force your logic into a request-response cycle is fundamentally flawed. Vercel functions are optimized for short, bursts of activity, not for long-term background processing.

Processes that run for 10, 20, or 60 minutes need a different environment. You should migrate these heavy jobs to a persistent server, such as a VPS or a dedicated queue worker infrastructure. Tools like Celery paired with Redis are industry standards for these types of tasks. By decoupling these tasks, you gain the ability to process them for as long as they need without worrying about timeouts or infrastructure-imposed limits.

You do not need to abandon Vercel entirely to do this. Instead, your Next.js application should act as a command center. When the user initiates an action that requires a long-running process, your Vercel function simply pushes a job into a queue or triggers a webhook on your external worker. This maintains a fast, responsive frontend for the user while offloading the heavy work to a system built for sustained execution.

This hybrid approach keeps your application responsive. The user receives a message such as 'Task started' and can check back later, or be notified via an email once the external worker finishes the work. This is the only reliable way to handle high-complexity, time-consuming operations in a modern web architecture.

Common gotchas and trade-offs

Developers often fall into the trap of initiating a long task directly from the client side using a fetch request. This creates a brittle connection. If the user closes their browser window, loses Wi-Fi connection, or navigates away, the HTTP request is aborted by the client. If your serverless function is waiting for that connection to stay active, it may also fail or terminate prematurely.

To build a resilient system, you must decouple the UI from the processing layer. Using an external trigger—such as a cron job service—ensures that the execution is not reliant on a user's active browser session. By calling an endpoint via a service like cron-job.org, you ensure the request is triggered correctly on a schedule, or you can design your architecture to store the 'job' in a database and have a background process poll for new work.

Another point to watch is how different parts of your code share the same configuration. If you set maxDuration = 300 in a shared layout file, it applies to all routes within that segment. This can lead to unexpected cost spikes if you have many lightweight functions that do not actually need the extended duration. Be precise with your configuration; apply high timeouts only to the specific files that strictly require them.

Finally, always monitor your error logs for 'Function duration exceeded' messages. These logs are a direct indicator that you are pushing against your current limits. Use these logs to identify if you are nearing the 300-second cap or if you need to optimize your algorithms to be more efficient, rather than simply extending the timeout duration further.

Frequently asked questions

Does maxDuration 300 work on Vercel Hobby?

Yes, but you must opt-in to Fluid Compute. Ensure your Next.js project is configured correctly and check the Vercel dashboard to see if your plan has any specific usage constraints enabled.

Will my function stay alive if the client disconnects?

Not necessarily. Vercel's execution environment is tied to the request lifecycle unless you explicitly use background utilities like waitUntil or trigger the task via an asynchronous worker pattern.

What is the best way to handle 10-minute tasks?

Do not use Vercel Serverless Functions for tasks exceeding 300 seconds. Move the logic to a persistent backend service, such as a VPS running a worker process, and call it via an API or webhook.

Sources & further reading

About the author

Tushar Gautam is a full-stack & ai product engineer in India. He builds AI SaaS products such as an AI video ad generator, a RAG chatbot platform and a Razorpay-powered report service, mostly with Next.js, Flask and the Gemini API. See the projects, GitHub or LinkedIn.

This article was drafted with the help of AI (Google Gemini) from official documentation and published by Tushar Gautam. Spotted an error? Let me know.