Skip to main content

Streaming Responses

res.json()/res.send() cover the common case: figure out the whole answer, send it back in one shot. Streaming is for the other case, sending a response in pieces over time, when there's no single complete answer to wait for, a periodic update pushed to a still-open connection, for as long as the client stays around.

The tools for it

HttpResponse adds three methods for this, on top of res.json()/res.send()/res.end():

MethodWhat it does
res.flushHeaders()Sends the status code and headers immediately, without ending the response (normally these wait until the response is finished)
res.write(chunk)Sends one piece of data without ending the response, so you can call it again
res.onAbort(callback)Runs if the client disconnects mid-stream, your chance to clean up anything still running (a timer, an interval)

These work identically on either HTTP engine.

Server-Sent Events

The most common concrete use is Server-Sent Events (SSE): a one-directional stream of updates over a single, long-lived connection, no polling required on the client side.

@Get('/events')
async streamEvents(@Response res: HttpResponse) {
res.setHeader('content-type', 'text/event-stream');
res.flushHeaders();

const interval = setInterval(() => {
res.write(`data: ${JSON.stringify({time: Date.now()})}\n\n`);
}, 1000);

res.onAbort(() => clearInterval(interval));
}

The content-type marks this as an event stream rather than a normal response, flushHeaders() sends that immediately instead of waiting, and the interval writes a new chunk every second for as long as the connection is open. onAbort stops the timer once the client disconnects, so nothing keeps running against a connection nobody's reading anymore.

There's no explicit "done" step here, and that's expected: once a handler starts writing chunks, RapidREST treats the response as handler-owned and won't also try to send its own response on top or time it out the way it would a handler that simply never returned.

When to reach for something else

Need the client to send data back over the same connection, not just receive it? See WebSockets. Just serving a file? BaseStaticRoute already does that without any of this, reading the whole file into memory and sending it as one normal response. Streaming earns its keep specifically for endpoints that need to push data out gradually, not as a general performance technique, most endpoints are simpler and better off staying that way.