Orientation Arc
Routing Algorithms
Rendering and JSX
Runtime Adapters
Middleware Ecosystem
Developer Helpers
System Utilities
The following files were used as context for generating this wiki page:
Streaming Utilities in Hono provide the infrastructure necessary for handling long-lived HTTP responses, server-sent events (SSE), and incremental rendering of HTML. By leveraging standard ReadableStream and WritableStream primitives, these utilities enable efficient, non-blocking data delivery, which is critical for real-time applications and optimized web performance.
At the architecture level, Hono abstracts the low-level complexities of stream management and browser-to-server connection handling. The primary objective is to allow developers to transmit data to the client as it becomes available, rather than waiting for an entire document or payload to be generated. This is achieved through a consistent interface that sits atop standard web APIs, ensuring compatibility across different JavaScript runtimes like Cloudflare Workers, Node.js, and Bun.
These utilities are deeply integrated into the Hono request/response lifecycle. Components like StreamingApi and SSEStreamingApi manage the communication pipes, while high-level helpers like stream, streamText, and streamSSE simplify the orchestration of these pipes. By centralizing the logic for chunked encoding, cleanup of abort events, and error propagation, these utilities ensure that streaming remains predictable and memory-efficient.
The StreamingApi class provides the foundational interface for writing chunks to an underlying WritableStream. It handles the conversion of strings to byte buffers, supports writeln for convenience, and maintains internal flags to track the stream's state, preventing redundant or erroneous operations once a stream has been aborted or closed.
Sources: src/utils/stream.ts:6-98, src/helper/streaming/sse.ts:13-45
The SSE implementation extends the base streaming API to enforce the specific format required by the SSE protocol (data:, event:, id:, etc.). The writeSSE method performs validation to ensure that headers like event or id do not contain illegal newline characters, which would terminate the message prematurely.
Warning
SSE message fields must not contain \r or \n. The writeSSE method throws an Error if these characters are detected in event, id, or retry fields to ensure protocol integrity.
Sources: src/helper/streaming/sse.ts:18-44
Streaming in Hono includes specific handling for platform inconsistencies, particularly regarding the ReadableStream lifecycle. In older versions of Bun, the ReadableStream used for response objects was not always automatically cancelled upon request abort. The stream and streamSSE helpers add event listeners to the request signal to manually invoke stream.abort() when an abort event occurs.
Sources: src/helper/streaming/stream.ts:15-22, src/helper/streaming/sse.ts:80-87
The renderToReadableStream function allows for incremental generation of HTML content from JSX trees. It tracks dependencies (callbacks) and resolves them as they become available. This mechanism is the backbone of Hono's streaming support for JSX, enabling components to suspend rendering until data is fetched.
Note
renderToReadableStream monitors cancelled status on each tick. If a stream is cancelled, it stops pushing data, which prevents memory leaks or unnecessary processing in the middle of long-running rendering tasks.
Sources: src/jsx/streaming.ts:142-216
Error handling is implemented through standard try-catch-finally patterns in the main runner functions (run for SSE and anonymous wrappers for general streams). When an error occurs in the callback, the onError hook is triggered.
Sources: src/helper/streaming/stream.ts:26-42, src/helper/streaming/sse.ts:47-68
The following example shows how to use the streamText utility to push data to the client incrementally.
import { Hono } from 'hono'
import { streamText } from 'hono/streaming'
const app = new Hono()
app.get('/stream', (c) => {
return streamText(c, async (stream) => {
await stream.writeln('Starting stream...')
await stream.sleep(1000)
await stream.write('Streaming complete.')
})
})Sources: src/helper/streaming/text.ts:6-15