With Fluid compute on, a Vercel Function serves many requests from one instance and can accept WebSocket connections, and on Pro or Enterprise it can run for up to 800 seconds (30 minutes in beta). We run Monogram Tools on Fluid compute, give our longest single-invocation agent job the full 800 seconds, and serve live cursors over a WebSocket upgrade on a Vercel Function with Redis pub/sub behind it.
What is the maximum duration of a Vercel Function?
On Fluid compute, every plan defaults to 300 seconds. Hobby stops there. Pro and Enterprise can raise a function to 800 seconds with maxDuration, and to 1,800 seconds in beta on supported Node.js, Bun and Python versions, set per function rather than as a project default. Anything that runs past its limit ends with a 504 FUNCTION_INVOCATION_TIMEOUT.
Journey, our site-walk tool in Monogram Tools, takes the full 800 seconds. Its internal deadlines scale with that ceiling, so each walk gets about 2.7 times the time the 300-second default allows. Most of our routes stay at the default; a longer ceiling is a decision per route, not a project setting.
What is Fluid compute, and should it be on?
Fluid compute is Vercel's execution model for Functions. One instance handles several invocations at once, idle instances are reused before new ones start, unhandled errors do not take down the other requests on the instance, and you pay for CPU only while your code is running rather than for wall-clock time, plus provisioned memory for as long as an instance is running, shared across the requests on it. It has been on by default for new projects since April 23, 2025; older projects turn it on in settings or with "fluid": true in vercel.json.
Fluid compute is on for every deployment of Monogram Tools, including previews. For an app that calls models, much of a request's life is spent waiting on a response, and Active CPU pricing does not bill that wait.
When does a long maxDuration fail the deploy?
When a route asks for more than the plan allows. The 800-second ceiling only exists with Fluid compute on, so 800 fails on a project without it. In our experience the limit is enforced when the deploy is created rather than during the build, so the route builds cleanly, then the deploy is rejected and the site stays on its previous version.
We run a unit test that scans every API route's maxDuration export and fails if any exceeds 800, so a typo-level mistake fails in CI instead of at deploy.
What should you do when a job needs longer than 800 seconds?
Split it. A function's maximum duration is a hard edge, and stretching toward the 30-minute beta only postpones the problem if the job's length depends on its input. Vercel's own guidance for unbounded work is Vercel Workflows, where a run carries on across invocations and has no duration limit.
AEO Audit is the job that taught us this. It makes about 60 grounded model calls, which our spec records as roughly 45 minutes of serial work at measured engine latency. Under a 300-second ceiling it needed a 150-second soft deadline, and no single-invocation ceiling would have held it. We moved it onto Workflows.
Does Vercel support WebSockets?
Yes. Vercel Functions on Fluid compute accept WebSocket connections natively on all plans. The feature entered public beta in June 2026 and became generally available on October 20, 2026. A connection stays pinned to the instance that accepted it for its whole life, one instance can hold many connections, and every connection closes when the function reaches its maximum duration. Idle connections do not accrue Active CPU charges, but provisioned memory bills while the instance is open.
Live cursors in Monogram Tools run on this. Everyone in a workspace who has the dashboard open is drawn as a pointer, and the room those pointers meet in is the workspace itself. We check the caller before accepting the upgrade, so a socket that should not exist is never opened.
How do WebSockets work in Next.js on Vercel?
Next.js has no built-in upgrade API, so Vercel provides upgradeWebSocket() from @vercel/functions, returned from a route handler's GET. Other frameworks use ws, Socket.IO or their own helpers.
Our cursor room is built on tickroom, an npm package one of our engineers wrote for rooms on serverless. We call createRoom from its Vercel adapter with Vercel's WebSocket upgrade function passed in. It runs a leased fixed-timestep tick loop and a WebSocket relay, with Redis pub/sub as the bus.
How do you share state across WebSocket connections on different instances?
Put it outside the function. In-memory state reaches only the connections on the same instance, and a reconnect can land anywhere, so Vercel recommends an external store such as Redis for rooms, presence and pub/sub.
Our cursors use Redis pub/sub as the bus between instances. Our subscriber runs over a TCP Redis connection with ioredis, which tickroom requires, rather than a REST client.
How do you keep a socket alive past the function's maximum duration?
You do not; you hand off before it. Every connection closes at the maximum duration, so clients need reconnect logic and long-lived server loops need a successor.
The cursor routes run at 300 seconds, and the ticker hands off to a fresh invocation every 270 seconds. In tickroom's own measurements, its handoffs on 300-second routes lost zero ticks.
Is module-level state safe on Fluid compute?
It is shared, which is both the benefit and the risk. Because concurrent requests share an instance, anything at module scope is visible to all of them for as long as the instance lives.
The Usage tab in Monogram Tools keeps its spend report in a module-level cache, per warm instance, for 60 seconds. That is safe because every workspace's entry is keyed by workspace and month, so one workspace's request cannot hit another workspace's entry. Anything request-scoped, such as the current user, belongs in the request, never in a module variable.
When not to use a long-running Vercel Function
Do not use a long ceiling for work that must survive a crash or a lost instance. An in-flight invocation dies with its instance, and after() or waitUntil work dies with it. That is the job Workflows exists for.
Do not reach for WebSockets when the server only pushes. For one-way streaming, Vercel recommends Server-Sent Events, which browsers reconnect on their own.
Our meeting relays, which need a socket server that lives as long as a room, run in Vercel Sandbox instead, one per room on an exposed port, because a function socket always ends at the function's maximum duration.
Mind the cost of an open socket. It keeps its instance's memory billed until it closes, shared across every connection on that instance.
If your app keeps running into the function ceiling, our Next.js and Vercel development team can help you decide what belongs in a function and what does not; get in touch.
FAQ
Is the 30-minute maximum duration generally available? No. 800 seconds is generally available on Pro and Enterprise; 1,800 seconds is in beta.
Does Hobby get 800 seconds? No. Hobby is capped at 300 seconds.
Can I use Socket.IO on Vercel? Yes, with the WebSocket transport set explicitly on the client.
Do WebSocket connections survive a deployment? Existing connections stay on the old deployment until they close; new connections may reach the new deployment.
Where can I read more about our Vercel work? See our Vercel technology page.

