---
title: "Streaming Utilities"
description: "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 `Readabl..."
last_updated: "2026-07-02T09:13:46.814068+00:00"
canonical_url: "https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/rendering-jsx/streaming-utilities"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [src/context.ts](https://github.com/blade47/hono/blob/main/src/context.ts)
- [src/jsx/dom/render.ts](https://github.com/blade47/hono/blob/main/src/jsx/dom/render.ts)
- [src/adapter/aws-lambda/handler.ts](https://github.com/blade47/hono/blob/main/src/adapter/aws-lambda/handler.ts)
- [src/jsx/streaming.ts](https://github.com/blade47/hono/blob/main/src/jsx/streaming.ts)
- [src/helper/streaming/stream.ts](https://github.com/blade47/hono/blob/main/src/helper/streaming/stream.ts)
- [src/helper/streaming/sse.ts](https://github.com/blade47/hono/blob/main/src/helper/streaming/sse.ts)
- [src/jsx/components.ts](https://github.com/blade47/hono/blob/main/src/jsx/components.ts)
- [src/middleware/compress/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/compress/index.ts)
- [src/utils/stream.ts](https://github.com/blade47/hono/blob/main/src/utils/stream.ts)
- [src/middleware/jsx-renderer/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/jsx-renderer/index.ts)
- [src/helper/proxy/index.ts](https://github.com/blade47/hono/blob/main/src/helper/proxy/index.ts)
- [src/request.ts](https://github.com/blade47/hono/blob/main/src/request.ts)
- [src/adapter/lambda-edge/handler.ts](https://github.com/blade47/hono/blob/main/src/adapter/lambda-edge/handler.ts)
- [src/jsx/base.ts](https://github.com/blade47/hono/blob/main/src/jsx/base.ts)
- [src/middleware/etag/digest.ts](https://github.com/blade47/hono/blob/main/src/middleware/etag/digest.ts)
- [src/middleware/body-limit/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/body-limit/index.ts)
- [src/helper/streaming/index.ts](https://github.com/blade47/hono/blob/main/src/helper/streaming/index.ts)
- [src/utils/html.ts](https://github.com/blade47/hono/blob/main/src/utils/html.ts)
- [src/jsx/dom/server.ts](https://github.com/blade47/hono/blob/main/src/jsx/dom/server.ts)
- [src/client/fetch-result-please.ts](https://github.com/blade47/hono/blob/main/src/client/fetch-result-please.ts)
- [src/jsx/jsx-runtime.ts](https://github.com/blade47/hono/blob/main/src/jsx/jsx-runtime.ts)
- [src/helper/streaming/text.ts](https://github.com/blade47/hono/blob/main/src/helper/streaming/text.ts)
- [src/helper/ssg/ssg.ts](https://github.com/blade47/hono/blob/main/src/helper/ssg/ssg.ts)
- [src/hono-base.ts](https://github.com/blade47/hono/blob/main/src/hono-base.ts)
- [src/jsx/dom/client.ts](https://github.com/blade47/hono/blob/main/src/jsx/dom/client.ts)
</details>

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.

## Core Streaming API Surface

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.

```mermaid
classDiagram
    class StreamingApi {
        -writer: WritableStreamDefaultWriter
        +responseReadable: ReadableStream
        +aborted: boolean
        +closed: boolean
        +write(input)
        +writeln(input)
        +close()
        +abort()
    }
    class SSEStreamingApi {
        +writeSSE(message)
    }
    StreamingApi <|-- SSEStreamingApi
```
Sources: [src/utils/stream.ts:6-98](https://github.com/blade47/hono/blob/main/src/utils/stream.ts#L6-L98), [src/helper/streaming/sse.ts:13-45](https://github.com/blade47/hono/blob/main/src/helper/streaming/sse.ts#L13-L45)

## Server-Sent Events (SSE) Mechanism

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](https://github.com/blade47/hono/blob/main/src/helper/streaming/sse.ts#L18-L44)

## Stream Lifecycle and Bun Compatibility

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.

```mermaid
flowchart TD
    A["Request received"] --> B{"Is old Bun version?"}
    B -- Yes --> C["Add signal abort listener"]
    B -- No --> D["Create TransformStream"]
    C --> D
    D --> E["Create StreamingApi"]
    E --> F["Start async cb(stream)"]
    F --> G["return c.newResponse(stream.responseReadable)"]
```
Sources: [src/helper/streaming/stream.ts:15-22](https://github.com/blade47/hono/blob/main/src/helper/streaming/stream.ts#L15-L22), [src/helper/streaming/sse.ts:80-87](https://github.com/blade47/hono/blob/main/src/helper/streaming/sse.ts#L80-L87)

## Incremental JSX Rendering

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](https://github.com/blade47/hono/blob/main/src/jsx/streaming.ts#L142-L216)

## Error Handling and Cleanup

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.

| Hook Type | Responsibility |
| :--- | :--- |
| `onError` | Receives the `Error` and `StreamingApi` instance to perform custom error logic or logging. |
| `Finally` block | Guarantees that `stream.close()` is called regardless of execution success, ensuring resource cleanup. |

Sources: [src/helper/streaming/stream.ts:26-42](https://github.com/blade47/hono/blob/main/src/helper/streaming/stream.ts#L26-L42), [src/helper/streaming/sse.ts:47-68](https://github.com/blade47/hono/blob/main/src/helper/streaming/sse.ts#L47-L68)

## Usage Example: Basic Text Streaming

The following example shows how to use the `streamText` utility to push data to the client incrementally.

```typescript
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](https://github.com/blade47/hono/blob/main/src/helper/streaming/text.ts#L6-L15)

## Related

- [JSX Renderer](https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/rendering-jsx/jsx-renderer)


## Sitemap

See the full [sitemap](https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/llms.txt) for all pages in this wiki.
