Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cloudflare/partykit/llms.txt

Use this file to discover all available pages before exploring further.

PartyServer represents each WebSocket client as a Connection — a standard WebSocket extended with an ID, tags, per-connection state, and a server name. Connections are created automatically when a client upgrades to WebSocket and are passed to every relevant lifecycle hook. Understanding the Connection interface is key to building stateful, multi-client servers.

Connection

type Connection<TState = unknown> = WebSocket & {
  id: string;
  uri: string | null;
  tags: readonly string[];
  server: string;
  state: ConnectionState<TState>;
  setState(state: TState | ConnectionSetStateFn<TState> | null): ConnectionState<TState>;
  serializeAttachment<T = unknown>(attachment: T): void;   // deprecated
  deserializeAttachment<T = unknown>(): T | null;          // deprecated
}
Connection extends the platform WebSocket type, so all standard WebSocket methods and events (send, close, addEventListener, etc.) are available in addition to the PartyServer-specific fields below. The generic parameter TState types the state property and the argument to setState. Use it to avoid unsafe casts when accessing per-connection data:
const conn = this.getConnection<UserState>(id);
console.log(conn?.state?.username);
id
string
A unique identifier for this connection, generated by PartyServer (using nanoid) when the WebSocket is accepted. Clients can supply their own ID via the _pk query parameter; otherwise one is auto-generated. Stable for the lifetime of the connection.
uri
string | null
The URL of the original WebSocket upgrade request. Persisted in the WebSocket attachment so it survives hibernation and can be read in hibernating event handlers.
tags
readonly string[]
An array of tags assigned to this connection by getConnectionTags. Use these to group or categorize connections (e.g. by room, role, or subscription). Read-only — tags are set at accept time and cannot be changed afterwards.
server
string
The name of the Server instance this connection belongs to — equivalent to this.name on the server. Populated after the server is initialized.
This field is deprecated. Prefer reading this.name directly on your Server subclass instead of accessing it from the connection object.
state
ConnectionState<TState>
Arbitrary state associated with this connection. Read-only — use setState to update it. Persisted in the WebSocket attachment so it survives hibernation. The maximum serialized size is 2 KB.

send

Inherited from the platform WebSocket. Send a message to this specific connection.
connection.send(message: string | ArrayBuffer | ArrayBufferView): void
message
string | ArrayBuffer | ArrayBufferView
The message payload to deliver to this client.

close

Inherited from the platform WebSocket. Close this specific connection.
connection.close(code?: number, reason?: string): void
code
number
Optional WebSocket close code (e.g. 1000 for normal closure, 40004999 for application-defined codes).
reason
string
Optional human-readable reason string. Maximum 123 bytes (UTF-8).

setState

setState(
  state: TState | ConnectionSetStateFn<TState> | null
): ConnectionState<TState>
Update the state stored on this connection. Accepts either a new state value directly or an updater function that receives the previous state and returns the next state. The state is persisted in the WebSocket’s attachment storage so it survives hibernation.
state
TState | ((prevState: ConnectionState<TState>) => TState) | null
The new state value, or an updater function. Pass null to clear the state.
return
ConnectionState<TState>
The updated state (an immutable view of the value you passed).
Use the updater function form when you need to merge new values with existing state without reading connection.state separately:
connection.setState((prev) => ({
  ...prev,
  lastSeen: Date.now()
}));
Storing user data on connect:
interface UserState {
  username: string;
  role: "admin" | "member";
}

async onConnect(connection: Connection<UserState>, ctx: ConnectionContext) {
  const user = await authenticate(ctx.request);
  connection.setState({ username: user.name, role: user.role });
}

onMessage(connection: Connection<UserState>, message: WSMessage) {
  if (connection.state?.role === "admin") {
    // admins can broadcast to everyone
    this.broadcast(message);
  } else {
    connection.send("Permission denied");
  }
}

ConnectionContext

type ConnectionContext = {
  request: Request;
}
Passed as the second argument to onConnect and getConnectionTags. Provides access to the original HTTP upgrade request so you can read headers, query parameters, cookies, or other request metadata at connection time.
request
Request
The original HTTP upgrade request that initiated the WebSocket connection. Use this to read authentication tokens, session cookies, or URL query parameters.
async onConnect(connection: Connection, ctx: ConnectionContext) {
  const token = ctx.request.headers.get("Authorization");
  const url = new URL(ctx.request.url);
  const room = url.searchParams.get("room");
  // ...
}

ConnectionState

type ConnectionState<T> = ImmutableObject<T> | null
ConnectionState<T> is a deeply immutable view of the state value stored on a connection. It is null before any state has been set. The underlying value must be JSON-serializable because it is stored in the WebSocket attachment and survives hibernation.
The maximum serialized size of connection state is 2 KB. Storing larger values will fail silently or cause errors at runtime. For larger datasets, use Durable Object storage via this.ctx.storage on the server.
Common pattern — storing authentication data:
interface AuthState {
  userId: string;
  username: string;
  avatarUrl: string;
}

async onConnect(connection: Connection<AuthState>, ctx: ConnectionContext) {
  const session = await verifySession(ctx.request);
  if (!session) {
    connection.close(4001, "Unauthorized");
    return;
  }
  connection.setState({
    userId: session.userId,
    username: session.username,
    avatarUrl: session.avatarUrl
  });
  this.broadcast(`${session.username} joined`, [connection.id]);
}

WSMessage

type WSMessage = ArrayBuffer | ArrayBufferView | string
The type of messages passed to onMessage and accepted by broadcast and connection.send. Covers all message formats a WebSocket can carry:
VariantDescription
stringUTF-8 text message (most common for JSON payloads)
ArrayBufferRaw binary message
ArrayBufferViewA view into an ArrayBuffer, e.g. Uint8Array
onMessage(connection: Connection, message: WSMessage) {
  if (typeof message === "string") {
    const data = JSON.parse(message);
    // handle text/JSON message
  } else {
    // handle binary message
    const bytes = new Uint8Array(message as ArrayBuffer);
  }
}

Using tags for filtered broadcasts

Tags let you segment connections into logical groups and send messages only to a subset of clients — without iterating every connection manually.
export class ChatServer extends Server {
  async getConnectionTags(connection: Connection, ctx: ConnectionContext) {
    const url = new URL(ctx.request.url);
    // Assign the room name as a tag at connect time
    return [url.searchParams.get("room") ?? "general"];
  }

  onMessage(connection: Connection, message: WSMessage) {
    // Broadcast only to connections in the same room
    const room = connection.tags[0];
    for (const peer of this.getConnections(room)) {
      if (peer.id !== connection.id) {
        peer.send(message);
      }
    }
  }
}
Each connection supports up to 9 tags, each with a maximum length of 256 characters. Tags are set once at accept time via getConnectionTags and cannot be changed for the lifetime of the connection.

Build docs developers (and LLMs) love