---
title: Do Vercel Functions support WebSocket connections?
description: Vercel Functions serve WebSocket connections natively, in public beta on all plans. Learn how connections pin to instances, how to handle reconnects, and where to keep shared state.
url: "https://vercel.com/kb/guide/do-vercel-serverless-functions-support-websocket-connections"
published: 2025-11-03
last_updated: 2026-10-01
authors: Vercel
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

Vercel Functions serve WebSocket connections natively, so a client and your server-side code can exchange messages in both directions over one open connection. WebSocket support is in public beta on all plans and runs on Fluid Compute. Use it for realtime features such as interactive AI streaming, chat, multiplayer state, and collaborative editing. There's no separate socket server to run, because the WebSocket endpoint is itself a Vercel Function.

## Overview

In this guide, you'll learn:

- How WebSocket connections behave on Vercel Functions
  
- When to use Server-Sent Events (SSE) instead of WebSockets
  
- How to set up a WebSocket endpoint with `ws`, [Socket.IO](http://Socket.IO), or your framework
  
- How to handle reconnects and share state across function instances
  
- Which limits and pricing apply to WebSocket connections
  

## How WebSockets work on Vercel Functions

A WebSocket connection on Vercel starts as an HTTP `GET` request with an `Upgrade` header, and that request passes through the same controls as any other request to a Vercel Function. Routing Middleware, rewrites, Firewall rules, and rate limits all run before the upgrade completes. You can write Firewall rules that target the WebSocket request path, and rate limits apply to each upgrade request.

After the upgrade succeeds, three behaviors shape how a WebSocket application on Vercel works:

- **Pinning**: A connection stays on the function instance that accepted it for the connection's whole lifetime. Fluid Compute lets one instance hold many connections at once.
  
- **Placement**: A new connection can reach any instance, including when a client reconnects. After a deployment, new connections may reach the new deployment while existing connections stay on the previous deployment until they close.
  
- **Duration**: A connection closes when the function reaches its maximum duration, so every client needs reconnect logic.
  

## When to choose SSE over WebSockets on Vercel

Use Server-Sent Events (SSE) when data only flows from the server to the client, and use WebSockets when the client also sends a continuous stream of its own. Both run on Vercel Functions.

AI response streaming is the most common one-way case. A model generates tokens, the server sends them as they arrive, and the client submits its next prompt as a separate HTTP request. SSE delivers this over a standard HTTP response, and the browser's `EventSource` API reconnects automatically after a drop. On reconnect, the browser sends a `Last-Event-ID` header so your server can resume the stream. SSE streams are still bounded by the function's maximum duration, but the browser handles reconnection for you, while WebSocket reconnection and state resync are code you write yourself.

Choose WebSockets when the client pushes data continuously without waiting on a new request, as in multiplayer game state, collaborative editing, typing indicators, and live cursors. For a deeper comparison of the two protocols, see [WebSocket vs Server-Sent Events](https://vercel.com/i/websocket-vs-server-sent-events).

## How to set up a WebSocket endpoint

WebSockets require Fluid Compute, which is enabled by default for projects created on or after April 23, 2025. For an older project, turn it on in your project's **Settings** under **Functions**, then redeploy.

WebSockets in Vercel Functions behave like any distributed WebSocket server, so standard libraries work without extra configuration. With `ws`, create a Node.js HTTP server, attach a `WebSocketServer`, and export the HTTP server as the default export:

```typescript
import http from 'http';
import { WebSocketServer } from 'ws';

const server = http.createServer();
const wss = new WebSocketServer({ server });

wss.on('connection', (ws) => {
  ws.on('message', (data) => {
    ws.send(data);
  });
});

export default server;
```

This example echoes each message back to the client that sent it, at `wss://your-domain.com/api/ws`.

[Socket.IO](http://Socket.IO) works the same way on the server, but the [Socket.IO](http://Socket.IO) client defaults to HTTP long-polling, so configure it to use the WebSocket transport directly. Create the server in `api/socket-io.ts`:

```typescript
import http from 'http';
import { Server } from 'socket.io';

const server = http.createServer();
const io = new Server(server);

io.on('connection', (socket) => {
  socket.on('message', (data) => {
    socket.send(data);
  });
});

export default server;
```

Then point the client at the full [Socket.IO](http://Socket.IO) path and set `transports` to `['websocket']`:

```typescript
import { io } from 'socket.io-client';

const socket = io('https://your-domain.com', {
  // Socket.IO appends /socket.io to the path by default,
  // so the full path becomes /api/socket-io/socket.io
  path: '/api/socket-io/socket.io',
  transports: ['websocket'],
});
```

Python applications can use `python-socketio`, and Flask applications can use `Flask-SocketIO`. Both libraries implement the [Socket.IO](http://Socket.IO) protocol, so clients need a compatible [Socket.IO](http://Socket.IO) client.

## Which frameworks support WebSockets on Vercel

Frameworks with native WebSocket support serve connections on Vercel Functions without Vercel-specific configuration. Each framework below has a full example in the [Use with frameworks](https://vercel.com/docs/functions/websockets#use-with-frameworks) section of the WebSockets documentation.

- **Node.js server frameworks**: Express, Hono, and h3 serve connections through `ws` or the framework's own upgrade helper, with the server exported as the default export of the function file, such as `api/server.ts`.
  
- **Bun**: The Bun runtime supports the native `Bun.serve()` WebSocket API. Call `server.upgrade()` from the `fetch` handler, then define handlers in the `websocket` option.
  
- **Nitro and Nuxt**: Nitro's WebSocket support is powered by crossws. Enable `features.websocket` in your Nitro config, then export a handler from `defineWebSocketHandler()` in a route file. The [Nitro](https://vercel.com/templates/nitro/nitro-websockets-starter) and [Nuxt](https://vercel.com/templates/nuxt/nuxt-websockets-starter) starter templates deploy without changes.
  
- **Python**: Applications built on the Asynchronous Server Gateway Interface (ASGI) or Web Server Gateway Interface (WSGI) serve connections without a Vercel-specific upgrade API. Use FastAPI's `@app.websocket()` decorator, Django Channels, or `flask-sock` for Flask.
  
- **Next.js**: Next.js has no built-in API for WebSocket upgrades, so `@vercel/functions` provides `experimental_upgradeWebSocket()`. Return it from the `GET` export of a route handler.
  

Because Next.js is the one framework that needs a Vercel-specific API, here is the full route handler:

```typescript
import {
  experimental_upgradeWebSocket,
  type WebSocketData,
} from '@vercel/functions';

export async function GET() {
  return experimental_upgradeWebSocket((ws) => {
    ws.on('message', (data: WebSocketData) => {
      ws.send(data);
    });
  });
}
```

See the [`experimental_upgradeWebSocket()`](https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#experimental_upgradewebsocket) [reference](https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#experimental_upgradewebsocket) for the full API.

## How to handle reconnects and shared state for WebSocket connections

WebSocket applications on Vercel need two pieces of client and server logic beyond the endpoint itself, because connections close at the maximum duration and a reconnecting client can land on any instance.

### How to reconnect when a connection closes

Every WebSocket connection on Vercel closes when the function reaches its maximum duration, so treat a close as an expected event rather than an error. Reconnect logic should recreate the connection, resubscribe to any channels or topics, and reload the state the client needs to continue.

The following client reconnects with exponential backoff, which keeps it from retrying in a tight loop while the endpoint is unavailable:

```typescript
let socket: WebSocket;
let reconnectDelay = 1000;

function connect() {
  socket = new WebSocket('wss://your-domain.com/api/ws');

  socket.addEventListener('open', () => {
    reconnectDelay = 1000;
  });

  socket.addEventListener('message', (event) => {
    console.log(event.data);
  });

  socket.addEventListener('close', () => {
    setTimeout(connect, reconnectDelay);
    reconnectDelay = Math.min(reconnectDelay * 2, 30000);
  });
}

connect();
```

The reconnect delay starts at 1 second, doubles after each close up to 30 seconds, and resets to 1 second once a connection opens. If many clients tend to connect at the same moment, add a random offset to the delay so their reconnects spread out.

### How to share state across function instances

New WebSocket connections aren't guaranteed to reach the same function instance, and in-memory variables only reach the connections on the instance that holds them. Without a shared store, two clients in the same chat room can connect to different instances and never see each other's messages. Built-in broadcast helpers have the same boundary, so Bun's `server.publish()` only reaches sockets on the same instance.

Keep durable state, presence, counters, rooms, and pub/sub coordination in an external data store. [Redis from the Vercel Marketplace](https://vercel.com/marketplace/redis) is reachable from every instance and every deployment. In a chat app, each instance publishes incoming messages to a Redis channel and subscribes to that channel, so a message from a user on one instance reaches users connected to another. [Publish and subscribe to realtime data on Vercel](https://vercel.com/kb/guide/publish-and-subscribe-to-realtime-data-on-vercel) compares the options for realtime fan-out.

## WebSocket limits and pricing on Vercel

WebSocket connections run on Vercel Functions and follow the same [limits](https://vercel.com/docs/functions/limitations) and [pricing model](https://vercel.com/docs/functions/usage-and-pricing) as any other function invocation. The function's maximum duration sets how long a single connection can stay open:

| Plan       | Default | Maximum | Extended maximum (beta) |
| ---------- | ------- | ------- | ----------------------- |
| Hobby      | 300s    | 300s    | Not available           |
| Pro        | 300s    | 800s    | 1,800s                  |
| Enterprise | 300s    | 800s    | 1,800s                  |

The extended maximum is available on the Node.js, Bun, and Python runtimes. Set durations above 800s per function, with `maxDuration` in `vercel.json` or in a Next.js route file, rather than as a project default. See [Configuring maximum duration](https://vercel.com/docs/functions/configuring-functions/duration) for each method.

Vercel Functions on Fluid Compute bill for Active CPU, Provisioned Memory, and Invocations. Active CPU applies only while your code processes messages, so an idle connection doesn't accrue CPU time. Provisioned Memory bills for the lifetime of the instance, which means an open connection keeps its instance's memory billable until the connection closes. One instance holds many connections, so that memory cost is shared across every connection on the instance. Data sent over the connection counts toward Fast Data Transfer and Fast Origin Transfer.

## Next steps

Deploy the [Nitro WebSockets starter](https://vercel.com/templates/nitro/nitro-websockets-starter) to begin from working code, or [start a new project](https://vercel.com/new) and add a WebSocket endpoint with the setup above.

## Related resources

- [WebSockets on Vercel Functions](https://vercel.com/docs/functions/websockets)
  
- [Fluid Compute](https://vercel.com/docs/fluid-compute)
  
- [Vercel Functions limits](https://vercel.com/docs/functions/limitations)
  
- [Publish and subscribe to realtime data on Vercel](https://vercel.com/kb/guide/publish-and-subscribe-to-realtime-data-on-vercel)
  
- [Realtime chat with WebSockets](https://vercel.com/kb/guide/real-time-chat-websockets)
  
- [Build Figma-style multiplayer cursors with WebSockets on Vercel](https://vercel.com/kb/guide/real-time-board-nextjs-fastapi)
  
- [Build Notion-style real-time presence with WebSockets on Vercel](https://vercel.com/kb/guide/real-time-presence-hono-react)
  
- [Streaming with Vercel Functions](https://vercel.com/docs/functions/streaming-functions)
  
- [WebSocket vs Server-Sent Events](https://vercel.com/i/websocket-vs-server-sent-events)
  

## Frequently asked questions

### Are WebSockets on Vercel still in beta?

Yes. WebSocket support for Vercel Functions entered public beta on June 22, 2026, and Python support followed on July 23, 2026. Behavior and APIs may change during the beta. WebSockets are available on all plans and require Fluid Compute, which is enabled by default for projects created on or after April 23, 2025.

### How long can a WebSocket connection stay open on Vercel?

A WebSocket connection stays open until the function reaches its maximum duration. That's 300s on Hobby. On Pro and Enterprise, the default is 300s, you can configure up to 800s, and an extended maximum of 1,800s is in beta for Node.js, Bun, and Python functions. Every connection eventually closes, so add reconnect logic to your client.

### Do I need a separate WebSocket server to use WebSockets on Vercel?

No. The WebSocket endpoint is a Vercel Function, so there's no standalone socket server to provision or scale. Standard libraries such as `ws` and [Socket.IO](http://Socket.IO) work without extra configuration, and one function instance handles many connections at once. To share state across instances, use an external store such as Redis.

### How much do WebSocket connections cost on Vercel?

WebSocket connections follow the standard Vercel Functions pricing model on Fluid Compute, billed on Active CPU, Provisioned Memory, and Invocations. Active CPU applies only while your code processes messages, not while the connection sits idle. Provisioned Memory bills for the instance lifetime, so an open connection keeps its instance billable until it closes.

### Do WebSockets work with Next.js on Vercel?

Yes. Next.js doesn't expose an API for WebSocket upgrades, so use `experimental_upgradeWebSocket()` from `@vercel/functions` inside a route handler. Frameworks with native WebSocket support, including Express, Hono, Nitro, and FastAPI, serve connections without a Vercel-specific API.

## More Vercel Functions guides

- [How can I increase the limit of redirects or use dynamic redirects on Vercel?](/kb/guide/how-can-i-increase-the-limit-of-redirects-or-use-dynamic-redirects-on-vercel): Instructions on how to use Serverless Functions to handle redirects on Vercel.
- [Can I route based on letter casing on Vercel?](/kb/guide/can-i-route-based-on-letter-casing-on-vercel): Information on whether or not it is possible to route based on letting casing with Vercel.
- [Vercel vs Render](/kb/guide/vercel-vs-render): A detailed guide to Vercel vs Render: compute models, AI infrastructure, Docker and container image support, background workers, and when to choose each platform for your project.