Skip to main content
The @websocket decorator defines a WebSocket API that opens a bidirectional message channel between client and server. Unlike @stream (SSE-only), it can also handle events sent by the client (inEvents) and broadcast messages to other connections in the same namespace/room.

Basic Usage

Options

outEvents

Defines server → client event types using a Zod schema. Required option

inEvents

Defines client → server event types using a Zod schema. Required option
Inbound messages are validated against inEvents via the envelope contract. Events not declared in the schema, or payloads that fail validation, are not delivered to handlers and are treated as policy violations.

path

WebSocket endpoint path. Default: /{modelName}/{methodName} (camelCase)

namespace

A logical group that scopes routing/broadcast inside the same server. Sonamu.websocketRuntime.publishToRoom(roomId, event, data, namespace) only delivers to connections in the same namespace. Default: "default"

heartbeat

Heartbeat (ping) interval in milliseconds. Default: 30000 (30 seconds)

guards

Restricts who can connect.
Guard failures are rejected during the handshake and close with 1008 Policy Violation.

description

Adds a description for the WebSocket API.

resourceName

Specifies the resource name for the generated service file.

WebSocketContext

A @websocket-decorated method receives WebSocketContext<TOut, TIn> as its last argument.

ctx.ws.publish

Sends an event to this connection only.

ctx.ws.onMessage

Handles events sent by the client.

ctx.ws.onClose

Runs cleanup when the connection closes.

ctx.ws.waitForClose

Keeps the handler alive until the connection closes. WebSocket methods typically await this promise to wrap up.

ctx.ws.join / ctx.ws.leave

Joins or leaves a room, which is the broadcast unit.

ctx.ws.setUserId / ctx.ws.clearUserId

Attaches a user identifier to the connection so it can be targeted by publishToUser.

Broadcast

From outside the handler you can also push messages to other connections via Sonamu.websocketRuntime.

Combining With Other Decorators

@websocket cannot share a method with @api, @stream, or @upload. If you want to expose the same data via both a WebSocket subscription and a plain HTTP endpoint, split them into two methods — one with @api, the other with @websocket.

Constraints

1. Cannot be combined with @api / @stream / @upload

2. httpMethod is always GET

@websocket automatically sets httpMethod: "GET" because the WebSocket upgrade starts from a GET request.

3. Watch out for context providers that depend on createSSE / reply

In the WebSocket path, SSE helpers and FastifyReply access are meaningless and raise an error immediately. If your context setup depends on them, define a dedicated websocketContextProvider.

Client Usage (Web)

For each @websocket method, Sonamu auto-generates a useWebSocketChannel hook.
State returned from useWebSocketChannel:
Options:

Logging

The @websocket decorator emits a debug log on each invocation.

Compared to @stream

Next Steps

@stream

When one-way SSE streaming is enough

@api

Build a standard REST endpoint

@transactional

Wrap mutations in a transaction

@cache

Improve performance with caching