WebSockets in Truss models
A Truss WebSocket model implements a singlewebsocket method in place of the usual preprocess, predict, and postprocess methods. All input and output flows through the WebSocket object itself, not through arguments or return values. load still works as it does for HTTP models.
-
Initialize your Truss:
Terminal
-
Replace the
predictmethod inmodel/model.pywith awebsocketmethod. For example:model/model.py -
Set
runtime.transport.kindtowebsocketinconfig.yaml:config.yaml -
Deploy the model:
baseten model push --watch.
For more information, see truss init and baseten model push.
Constraints and behavior
- Your
websocketmethod controls message exchange. The example loops until the client disconnects. To close the connection from the server, callawait websocket.close(). - Define
websocketas an async method with one WebSocket argument. - Don’t implement
predict,preprocess, orpostprocessalongsidewebsocket. Truss rejects models that combine these methods. - Baseten accepts the connection for you, so don’t call
websocket.accept(). You can close the connection yourself when you’re done; otherwise Baseten closes it after yourwebsocketmethod returns.
Call the model
SetBASETEN_API_KEY to your API key. Replace {MODEL_ID} with your model ID, then use websocat to connect:
Terminal
Hello. The model replies with WS obtained: Hello. Press Ctrl+C to close the connection.
The path depends on the environment or deployment you’re calling:
- Environment:
wss://model-{MODEL_ID}.api.baseten.co/environments/{ENVIRONMENT_NAME}/websocket - Deployment:
wss://model-{MODEL_ID}.api.baseten.co/deployment/{DEPLOYMENT_ID}/websocket - Regional environment:
wss://model-{MODEL_ID}-{ENV_NAME}.api.baseten.co/websocket. See Regional environments. - Regional deployment:
wss://model-{MODEL_ID}-region-{REGION_SLUG}.api.baseten.co/websocket. See Regional deployments.
WebSockets in Chains
Chains wrap WebSockets in a reducedWebSocketProtocol object. Processing happens in run_remote as usual, but inputs and outputs both flow through the WebSocket itself using async send_* and receive_* methods (text, bytes, and json variants). A convenience receive method handles both str and bytes.
Example chainlet
chainlet.py
Constraints and behavior
- Define
run_remoteas an async method with aWebSocketProtocolargument. This protocol exposes a subset offastapi.WebSocket; you can’t callaccept(). Baseten has already accepted the connection by the time your chainlet runs. run_remoteaccepts no other arguments when using WebSockets.- The return type must be
None. Send any data back to the client through the WebSocket instead. - WebSockets are only supported on the entrypoint chainlet, not on dependencies.
- Unlike Truss models, Chains don’t require you to set
runtime.transport.kind.
Call the Chain
Save the example aschainlet.py, then deploy the Chain to its production environment:
Terminal
BASETEN_API_KEY set, replace {CHAIN_ID} with your Chain ID and use websocat to connect:
Terminal
dep. The Chain replies with Hello from dependency, WSEntrypoint.. Press Ctrl+C to close the connection.
Like models, chains accept WebSocket connections on either a deployment or environment path. For regional environments, use
wss://chain-{CHAIN_ID}-{ENV_NAME}.api.baseten.co/websocket. See Regional environments.See the WebSocket endpoint reference for full details.WebSockets with custom servers
Deploy a WebSocket server from a custom Docker image using thedocker_server configuration. This fits when you already have a WebSocket server packaged as a container, or when you need a runtime Baseten’s managed images don’t provide.
Configuration
Set the following inconfig.yaml:
config.yaml
predict_endpoint to your server’s WebSocket route and runtime.transport.kind to websocket. Use HTTP routes for the readiness and liveness probes. See the docker_server configuration reference for field definitions.
Deploy from the directory containing config.yaml:
Terminal
Call the model
WithBASETEN_API_KEY set, replace {MODEL_ID} with your model ID and use websocat to connect:
Terminal
predict_endpoint path on your server.
For more on custom server deployment, see Custom servers.
Deployment and concurrency considerations
Scheduling
An established WebSocket connection stays on its replica and counts toward that replica’s concurrency while open, including idle periods. Configure autoscaling for the number of simultaneous connections your deployment needs. Close idle connections when your application no longer needs them.Connection lifetime
Connections can close when the client or server ends the session, a replica restarts, or a network failure occurs. Design clients to reconnect and restore any application state they need. A new connection can reach a different replica.Concurrency changes
Lowering the concurrency target doesn’t close existing connections. Open WebSockets keep running until they close naturally, even if a replica ends up above the new target. For example, if a replica holds 10 active WebSockets and you changeconcurrency_target from 10 to 5, Baseten leaves all 10 open. They drain as clients or servers close their connections.
Promotion
You can promote a WebSocket model or chain to an environment through the REST API or UI, the same way you promote HTTP deployments. For more information, see Environments. On promotion, Baseten routes new connections to the new deployment, but existing connections stay on the previous deployment until they terminate. This means older deployments can take longer to scale down than HTTP deployments: their connections outlive the promotion.Maximum message size
Baseten enforces a 100 MiB limit on individual messages sent over a WebSocket. Both clients and models are capped at 100 MiB per outgoing message. There’s no cap on the total data sent over a connection’s lifetime.Monitoring
Use the Metrics page to monitor connection volume, duration, and transferred bytes. WebSocket measurements describe connections rather than individual messages.Inference volume
The Metrics page tracks inference volume as the number of connections per minute. Baseten publishes each data point after the connection closes, so every point carries the status the connection ended with. Two families of status codes appear for WebSocket deployments:- HTTP status codes for connections that failed before the WebSocket upgrade completed.
- WebSocket close codes for connections that completed the upgrade and later closed.
HTTP status codes
WebSocket close codes
The Metrics page reports the following WebSocket close codes. See the IANA registry for registered code definitions.
For managed Truss models and Chains, these cases help diagnose handler problems:
- Truss closes with
1000when the handler returns normally. - Truss closes with
1003when the deployment has no WebSocket handler. Check that you deployed a model with awebsocketmethod or a Chain with a WebSocket entrypoint. - Truss closes with
1011when the handler raises an uncaught exception. Check the deployment logs for the error.
The Metrics page shows HTTP
408 and 504 and the WebSocket close codes listed here. It excludes other status codes. The recorded status describes the upstream connection and can differ from the close code your client observes.End-to-end connection duration
Baseten measures duration from when it starts handling the connection request until the request ends, including time before the WebSocket upgrade completes. The Metrics page reports p50, p90, p95, and p99 after the connection ends. For speech applications, a connection can contain multiple utterances. Measure first partial transcript, finalization delay, or first audio in your client. Connection duration doesn’t measure these events. See Voice inference performance for timing definitions and concurrency measurements.Connection input and output size
Cumulative message payload bytes transferred over the connection’s lifetime, reported at p50, p90, p95, and p99:- Connection input size: Bytes sent by the client to the server.
- Connection output size: Bytes sent by the server to the client.
Connect to a speech model
For real-time transcription with a model from the Model Library, start with the speech quickstart. Each model defines its audio format, message types, and completion signals. Follow the transcription WebSocket reference for the Qwen3-ASR or Whisper protocol. Send audio and receive transcripts concurrently. After sending the end-of-audio message, keep receiving until the model confirms completion. For Qwen3-ASR, wait for a final transcription withis_end_of_audio_flush: true. A normal WebSocket close alone doesn’t confirm that all audio was transcribed.
Handle model error messages as failures and use receive timeouts to avoid waiting indefinitely. The quickstart client demonstrates completion handling, timeouts, and task cleanup.