Connection keepalive
Learn how keepalive keeps a WebSocket connection open between streams in Soniox Text-to-Speech, and why it does not keep an individual stream open.
Overview
Keepalive keeps an idle WebSocket connection open between streams, so you can start the next stream on the same socket without reconnecting. This is useful in a conversational agent, where there are gaps between turns while the user speaks or an upstream LLM is thinking.
To keep the connection open, send a keepalive control message:
Keepalive is a connection-level signal. It does not trigger speech generation and has no effect on any stream.
Keepalive does not keep a stream open. Once a stream has started, the server expects text for it to keep arriving. If more than a few seconds pass without a text message for the stream and you have not sent text_end: true, the stream is terminated with a request_timeout error, no matter how many keepalives you send.
Connection timers vs stream timers
There are two separate timers, and keepalive only affects the connection.
| Scope | Timer resets on | When it fires |
|---|---|---|
| Stream | A text message for that stream_id | A few seconds without text and no text_end: true: the stream ends with request_timeout. |
| Connection | Any client message, including keep_alive | About 40 seconds with no active stream and no message: the connection is closed as idle. |
While a stream is active, the connection is never closed as idle. The connection timer only matters in the gaps between streams.
Send text continuously within a stream
A stream is a single, continuous piece of text, for example one agent reply. Send the first text chunk promptly after the config message, keep sending chunks without pausing for more than a few seconds, and send text_end: true as soon as the text is complete. The server then generates the remaining audio and terminates the stream cleanly. See Stream termination.
If you do not know when the next piece of text will arrive, do not hold the stream open. Send text_end: true, keep the connection open with keepalives, and start a new stream with a new stream_id when the next text is ready.
For example, this sequence fails: the client sends text without text_end: true, then only keepalives while waiting for more text.
Audio for the text is delivered, but a few seconds after the last text message the server sends a request_timeout error followed by terminated: true for turn-1.
When to use keepalive
Send a keepalive message when no stream is active and you are waiting for the next text, for example between agent turns or while an LLM generates the next reply. You can also send keepalives on a fixed interval while a stream is active. They are harmless, but they do not extend the stream's text window.
Key points
- Keepalive keeps the connection open between streams. It does not keep a stream open.
- Send a keepalive every 20–30 seconds when no stream is active, to stay under the 40-second idle limit.
- Keepalive applies to the whole WebSocket connection, not to a specific
stream_id. - Keepalive works from the moment the connection opens. The connection needs a
message at least every 40 seconds and has no deadline for its first stream.
See WebSocket
authentication. A
connection that still sends
api_keyin the config message follows the rules in Migrate WebSocket authentication.
A held connection costs a connection slot
Keepalives keep a connection open for as long as you send them. There is no limit on how long a connection may wait between streams. Every open connection counts against your connection limit, so close connections you no longer need rather than keeping them alive out of habit.