---
title: "Execution Context"
description: "The Context class manages the complete execution lifecycle for incoming HTTP requests src/context.ts. It encapsulates routing parameters, request headers, environment bindings, and response generat..."
last_updated: "2026-10-12T08:14:12.710392+00:00"
canonical_url: "https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/core-engine/execution-context"
---

<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/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts)
- [src/request.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/request.ts)
- [src/types.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/types.ts)
- [src/adapter/aws-lambda/handler.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/aws-lambda/handler.ts)
- [src/helper/streaming/sse.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts)
- [src/helper/route/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/route/index.ts)
- [src/middleware/jsx-renderer/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts)
- [src/hono-base.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/hono-base.ts)
- [src/middleware/request-id/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/request-id/index.ts)
- [src/helper/streaming/stream.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/stream.ts)
- [src/helper/streaming/text.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/text.ts)
- [src/middleware/timing/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/timing/index.ts)
- [src/adapter/cloudflare-pages/handler.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts)
- [src/adapter/aws-lambda/types.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/aws-lambda/types.ts)
- [src/middleware/context-storage/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/context-storage/index.ts)
- [src/jsx/context.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts)
- [src/helper/adapter/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts)
- [src/adapter/bun/server.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/bun/server.ts)
- [src/adapter/lambda-edge/conninfo.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/lambda-edge/conninfo.ts)
- [src/middleware/language/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/language/index.ts)
- [src/middleware/secure-headers/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/secure-headers/index.ts)
- [src/adapter/netlify/handler.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/netlify/handler.ts)
- [src/helper/testing/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/testing/index.ts)
- [src/middleware/jwt/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwt/index.ts)
- [src/middleware/ip-restriction/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/ip-restriction/index.ts)
</details>

## Overview

The `Context` class manages the complete execution lifecycle for incoming HTTP requests [src/context.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L293-L361). It encapsulates routing parameters, request headers, environment bindings, and response generation utilities within a unified interface passed to handlers and middleware [src/context.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L315-L434), [src/request.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/request.ts#L94-L198).

Sources: [src/context.ts:293-361](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L293-L361)

Sources: [src/context.ts:315-434](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L315-L434), [src/request.ts:94-198](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/request.ts#L94-L198)

## Context Lifecycle and Internal State

### Constructor Initialization and Request Wrapping

The `Context` class constructor takes a raw Web Standard `Request` object and an optional `ContextOptions` record [src/context.ts:352-361](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L352-L361). It retains the underlying request as `#rawRequest` and initializes instance parameters such as execution contexts, environment bindings, not-found handlers, path specifications, and routing match results if provided [src/context.ts:300-360](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L300-L360). 

Sources: [src/context.ts:352-361](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L352-L361)

Request parsing is deferred via the `.req` getter property, which lazily instantiates a `HonoRequest` wrapper around `#rawRequest`, `#path`, and `#matchResult` upon first access [src/context.ts:366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L366-L369). Similarly, Cloudflare Pages middleware integration constructs a `Context` instance by passing the event execution context alongside extended bindings [src/adapter/cloudflare-pages/handler.ts:60-64](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts#L60-L64).

Sources: [src/context.ts:366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L366-L369)

Sources: [src/adapter/cloudflare-pages/handler.ts:60-64](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts#L60-L64)

```typescript
constructor(req: Request, options?: ContextOptions<E>) {
  this.#rawRequest = req
  if (options) {
    this.#executionCtx = options.executionCtx
    this.env = options.env
    this.#notFoundHandler = options.notFoundHandler
    this.#path = options.path
    this.#matchResult = options.matchResult
  }
}
```
Sources: [src/context.ts:352-361](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L352-L361)

```typescript
return async (executionCtx) => {
  const context = new Context(executionCtx.request, {
    env: { ...executionCtx.env, eventContext: executionCtx },
    executionCtx,
  })
```
Sources: [src/adapter/cloudflare-pages/handler.ts:60-64](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts#L60-L64)

### Execution State and Response Tracking

An active `Context` instance maintains internal tracking flags and response fields throughout the handler execution cycle [src/context.ts:315-345](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L315-L345). The `finalized` boolean flag marks whether a response has been committed or set [src/context.ts:317](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L317). Platform-specific capabilities such as Cloudflare Workers event bindings are accessed through strict getters: the `event` getter verifies the presence of `respondWith` on the execution context, while the `executionCtx` getter validates standard platform contexts, throwing errors if accessed outside a supported environment [src/context.ts:377-397](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L377-L397).

Sources: [src/context.ts:315-345](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L315-L345)

Sources: [src/context.ts:317](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L317)

Sources: [src/context.ts:377-397](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L377-L397)

```typescript
get res(): Response {
  return (this.#res ||= createResponseInstance(null, {
    headers: (this.#preparedHeaders ??= new Headers()),
  }))
}

/**
 * Sets the Response object for the current request.
 *
 * @param _res - The Response object to set.
 */
set res(_res: Response | undefined) {
  if (this.#res && _res) {
    _res = createResponseInstance(_res.body, _res)
    for (const [k, v] of this.#res.headers.entries()) {
      if (k === 'content-type') {
        continue
      }
      if (k === 'set-cookie') {
        const cookies = this.#res.headers.getSetCookie()
        _res.headers.delete('set-cookie')
        for (const cookie of cookies) {
          _res.headers.append('set-cookie', cookie)
        }
      } else {
        _res.headers.set(k, v)
      }
    }
  }
  this.#res = _res
  this.finalized = true
}
```
Sources: [src/context.ts:403-434](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L403-L434)

> [!NOTE]
> Setting the response property (`c.res = ...`) automatically marks the context as finalized and copies existing header entries—such as preserving set-cookie arrays and skipping duplicate content types—into the incoming response instance [src/context.ts:414-434](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L414-L434).

Sources: [src/context.ts:414-434](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L414-L434)

The table below details the internal state properties managed directly within the `Context` class instance.

| Field / Property | Internal Variable | Type | Description |
| :--- | :--- | :--- | :--- |
| `req` | `#req`, `#rawRequest` | `HonoRequest \| undefined`, `Request` | Lazily wrapped request accessor and underlying fetch request [src/context.ts:300-301, 366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L300-L301) |
| `env` | `env` | `E['Bindings']` | Environment variables, secrets, and bindings object [src/context.ts:315](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L315) |
| `error` | `error` | `Error \| undefined` | Captured error object thrown during middleware or handler execution [src/context.ts:333](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L333) |
| `event` | `#executionCtx` | `FetchEventLike` | FetchEvent instance supporting `respondWith` [src/context.ts:336, 377-383](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L336) |
| `executionCtx` | `#executionCtx` | `ExecutionContext` | Platform execution context supporting methods like `waitUntil` [src/context.ts:336, 391-397](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L336) |
| `res` | `#res`, `#preparedHeaders` | `Response`, `Headers \| undefined` | Current response object and prepared headers buffer [src/context.ts:337, 341, 403-407](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L337) |
| `finalized` | `finalized` | `boolean` | Flag indicating whether the response has been sent or locked [src/context.ts:317](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L317) |

Sources: [src/context.ts:300-434](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L300-L434)

## Request Parameter and Header Accessors

### HonoRequest Initialization and Parameter Retrieval

The `Context` instance exposes incoming request properties through its `.req` property [src/context.ts:366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L366-L369). Accessing `c.req` triggers the lazy instantiation of a `HonoRequest` wrapper, combining the raw underlying `Request` object with route path variables and match results [src/context.ts:366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L366-L369). 

Sources: [src/context.ts:366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L366-L369)

```typescript
get req(): HonoRequest<P, I['out']> {
  this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult)
  return this.#req
}
```
Sources: [src/context.ts:366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L366-L369)

> [!NOTE]
> The `HonoRequest` instance is initialized precisely on first access (`this.#req ??= ...`), avoiding parsing overhead for requests that do not inspect parameters, headers, or query strings [src/context.ts:366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L366-L369).

Sources: [src/context.ts:366-369](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L366-L369)

## Variable Storage and Context Typing

### Context Variable Map and Generic Constraints

The `Context` class manages scoped variables across middleware and request handlers via a private `#var` instance of JavaScript's `Map` [src/context.ts:316](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L316). These variables are typed through the generic `E` constraint parameter extending `Env`, allowing applications to define strict typing for key-value pairs shared during request execution [src/context.ts:293-295](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L293-L295). 

Sources: [src/context.ts:316](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L316)

Sources: [src/context.ts:293-295](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L293-L295)

```typescript
#var: Map<unknown, unknown> | undefined
```
Sources: [src/context.ts:316](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L316)

> [!NOTE]
> The internal `#var` map is lazily initialized on first write or read operation, preventing unnecessary allocation for request contexts that do not utilize scoped variables [src/context.ts:316](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L316).

Sources: [src/context.ts:316](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L316)

## Response Construction and Helpers

### Response Instance Creation and Default Types

Response generation relies on underlying Web Standard constructor wrappers [src/context.ts:288-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L288-L291). The helper `createResponseInstance` wraps `new Response(body, init)`, providing the foundation for text, stream, and binary outputs [src/context.ts:288-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L288-L291). Additionally, `TEXT_PLAIN` defines the default UTF-8 plain text content type string [src/context.ts:279](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L279), while `setDefaultContentType` merges content type headers with existing header records [src/context.ts:281-286](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L281-L286).

Sources: [src/context.ts:288-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L288-L291)

Sources: [src/context.ts:279](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L279), [src/context.ts:281-286](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L281-L286)

```typescript
export const TEXT_PLAIN = 'text/plain; charset=UTF-8'

const setDefaultContentType = (contentType: string, headers?: HeaderRecord): HeaderRecord => {
  return {
    'Content-Type': contentType,
    ...headers,
  }
}

const createResponseInstance = (
  body?: BodyInit | null | undefined,
  init?: globalThis.ResponseInit
): Response => new Response(body, init)
```
Sources: [src/context.ts:279-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L279-L291)

> [!WARNING]
> Modifying headers after a response has been finalized forces Hono to instantiate a new underlying `Response` object to prevent mutation errors on immutable response streams [src/context.ts:516-518](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L516-L518).

Sources: [src/context.ts:516-518](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L516-L518)

### Stream SSE Execution Walkthrough

The `streamSSE` helper orchestrates Server-Sent Events by initializing a transform stream, invoking `c.header` to configure transport headers, and utilizing `createResponseInstance` to generate the final response [src/helper/streaming/sse.ts:72-100](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L72-L100), [src/context.ts:288-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L288-L291).

Sources: [src/helper/streaming/sse.ts:72-100](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L72-L100), [src/context.ts:288-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L288-L291)

1. `streamSSE` initializes a `TransformStream` and wraps it in an `SSEStreamingApi` instance [src/helper/streaming/sse.ts:77-78](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L77-L78).
2. `isOldBunVersion()` checks for legacy runtime behavior, binding an abort listener to `c.req.raw.signal` if necessary [src/helper/streaming/sse.ts:80-87](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L80-L87).
3. `contextStash.set` caches the context against the response readable stream to prevent premature garbage collection in Bun [src/helper/streaming/sse.ts:89-90](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L89-L90).
4. `c.header` sets required transport and protocol headers including `Transfer-Encoding`, `Content-Type`, `Cache-Control`, and `Connection` [src/helper/streaming/sse.ts:92-95](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L92-L95), [src/context.ts:515-527](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L515-L527).
5. `run` executes the user callback with error handling and automatic stream closure [src/helper/streaming/sse.ts:47-68](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L47-L68), [97](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L97).
6. `createResponseInstance` is invoked through response helpers to construct the final Response wrapping `stream.responseReadable` [src/helper/streaming/sse.ts:99](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L99), [src/context.ts:288-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L288-L291).

Sources: [src/helper/streaming/sse.ts:77-78](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L77-L78)

Sources: [src/helper/streaming/sse.ts:80-87](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L80-L87)

Sources: [src/helper/streaming/sse.ts:89-90](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L89-L90)

Sources: [src/helper/streaming/sse.ts:92-95](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L92-L95), [src/context.ts:515-527](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L515-L527)

Sources: [src/helper/streaming/sse.ts:47-68](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L47-L68), [src/helper/streaming/sse.ts:97](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L97)

Sources: [src/helper/streaming/sse.ts:99](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L99), [src/context.ts:288-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L288-L291)

```typescript
export const streamSSE = (
  c: Context,
  cb: (stream: SSEStreamingApi) => Promise<void>,
  onError?: (e: Error, stream: SSEStreamingApi) => Promise<void>
): Response => {
  const { readable, writable } = new TransformStream()
  const stream = new SSEStreamingApi(writable, readable)

  // Until Bun v1.1.27, Bun didn't call cancel() on the ReadableStream for Response objects from Bun.serve()
  if (isOldBunVersion()) {
    c.req.raw.signal.addEventListener('abort', () => {
      if (!stream.closed) {
        stream.abort()
      }
    })
  }

  // in bun, `c` is destroyed when the request is returned, so hold it until the end of streaming
  contextStash.set(stream.responseReadable, c)

  c.header('Transfer-Encoding', 'chunked')
  c.header('Content-Type', 'text/event-stream')
  c.header('Cache-Control', 'no-cache')
  c.header('Connection', 'keep-alive')

  run(stream, cb, onError)

  return c.newResponse(stream.responseReadable)
}
```
Sources: [src/helper/streaming/sse.ts:72-100](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L72-L100)

```mermaid
sequenceDiagram
    participant streamSSE as streamSSE (sse.ts)
    participant Context as Context (context.ts)
    participant header as header (context.ts)
    participant createResponseInstance as createResponseInstance (context.ts)

    streamSSE->>Context: c.header('Transfer-Encoding', 'chunked')
    Context->>header: header(name, value, options)
    streamSSE->>Context: c.newResponse(stream.responseReadable)
    Context->>createResponseInstance: createResponseInstance(body, init)
```
Sources: [src/helper/streaming/sse.ts:72-100](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L72-L100), [src/context.ts:288-291](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L288-L291)

> [!NOTE]
An internal `contextStash` WeakMap holds a reference to the active `Context` keyed by `stream.responseReadable`, ensuring the request context remains accessible throughout long-lived streaming connections [src/helper/streaming/sse.ts:70-90](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L70-L90).

Sources: [src/helper/streaming/sse.ts:70-90](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/sse.ts#L70-L90)

## Adapter Bindings and Environment Access

### Runtime Identification and Environment Resolution

Hono resolves environment bindings and execution contexts across heterogeneous JavaScript runtimes by combining runtime detection helpers with platform-specific adapter handlers. The `getRuntimeKey()` utility inspects `globalThis` properties and user agent strings to classify the active platform into one of the supported runtime identifiers [src/helper/adapter/index.ts:50-84](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts#L50-L84). Once identified, the `env()` helper dynamically dispatches to the correct environment provider, returning process environment variables or platform-native binding stores [src/helper/adapter/index.ts:10-41](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts#L10-L41).

Sources: [src/helper/adapter/index.ts:50-84](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts#L50-L84)

Sources: [src/helper/adapter/index.ts:10-41](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts#L10-L41)

| Runtime Key | Detection Mechanism | Environment Source |
| :--- | :--- | :--- |
| `bun` | `navigator.userAgent` starts with `Bun` | `process.env` |
| `node` | `navigator.userAgent` starts with `Node.js` or `process.release.name === 'node'` | `process.env` |
| `deno` | `navigator.userAgent` starts with `Deno` | `Deno.env.toObject()` |
| `workerd` | `navigator.userAgent` starts with `Cloudflare-Workers` | `c.env` |
| `edge-light` | `globalThis.EdgeRuntime` is a string | `process.env` |
| `fastly` | `globalThis.fastly !== undefined` | `{}` |
| `other` | Fallback when no platform signature matches | `{}` |

Sources: [src/helper/adapter/index.ts:8-48](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts#L8-L48)

```typescript
export type Runtime = 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'other'

export const env = <
  T extends Record<string, unknown>,
  C extends Context = Context<{
    Bindings: T
  }>,
>(
  c: T extends Record<string, unknown> ? Context : C,
  runtime?: Runtime
): T & C['env'] => {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const global = globalThis as any
  const globalEnv = global?.process?.env as T

  runtime ??= getRuntimeKey()

  const runtimeEnvHandlers: Record<string, () => T> = {
    bun: () => globalEnv,
    node: () => globalEnv,
    'edge-light': () => globalEnv,
    deno: () => {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      return Deno.env.toObject() as T
    },
    workerd: () => c.env,
    // On Fastly Compute, you can use the ConfigStore to manage user-defined data.
    fastly: () => ({}) as T,
    other: () => ({}) as T,
  }

  return runtimeEnvHandlers[runtime]()
}

export const knownUserAgents: Partial<Record<Runtime, string>> = {
  deno: 'Deno',
  bun: 'Bun',
  workerd: 'Cloudflare-Workers',
  node: 'Node.js',
}
```
Sources: [src/helper/adapter/index.ts:8-48](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts#L8-L48)

> [!NOTE]
> The `env()` helper requires an explicit runtime parameter or falls back to `getRuntimeKey()`, which inspects `navigator.userAgent` before checking runtime-specific global objects [src/helper/adapter/index.ts:17-23](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts#L17-L23).

Sources: [src/helper/adapter/index.ts:17-23](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/adapter/index.ts#L17-L23)

### Platform Adapter Handlers and Execution Contexts

Cloudflare Pages, AWS Lambda, and Netlify integrate with Hono by mapping native platform events and execution contexts into the standard `app.fetch()` signature [src/adapter/aws-lambda/handler.ts:268-272](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/aws-lambda/handler.ts#L268-L272), [src/adapter/cloudflare-pages/handler.ts:37-45](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts#L37-L45), [src/adapter/netlify/handler.ts:8](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/netlify/handler.ts#L8). Cloudflare Pages passes `eventContext.request`, environment bindings augmented with `eventContext`, and an execution options object containing `waitUntil` and `passThroughOnException` callbacks [src/adapter/cloudflare-pages/handler.ts:37-45](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts#L37-L45). 

Sources: [src/adapter/aws-lambda/handler.ts:268-272](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/aws-lambda/handler.ts#L268-L272), [src/adapter/cloudflare-pages/handler.ts:37-45](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts#L37-L45), [src/adapter/netlify/handler.ts:8](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/netlify/handler.ts#L8)

Sources: [src/adapter/cloudflare-pages/handler.ts:37-45](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts#L37-L45)

```typescript
export const handle =
  <E extends Env = Env, S extends Schema = BlankSchema, BasePath extends string = '/'>(
    app: Hono<E, S, BasePath>
  ): PagesFunction<E['Bindings']> =>
  (eventContext) => {
    return app.fetch(
      eventContext.request,
      { ...eventContext.env, eventContext },
      {
        waitUntil: eventContext.waitUntil,
        passThroughOnException: eventContext.passThroughOnException,
        props: {},
      }
    )
  }
```
Sources: [src/adapter/cloudflare-pages/handler.ts:32-46](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/cloudflare-pages/handler.ts#L32-L46)

AWS Lambda adapters process incoming API Gateway or ALB events via event processors (`EventV1Processor` and `EventV2Processor`), converting event payloads into standard `Request` instances and passing the raw `event`, `requestContext`, and `lambdaContext` through to `app.fetch()` [src/adapter/aws-lambda/handler.ts:252-272](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/aws-lambda/handler.ts#L252-L272). Similarly, Netlify's adapter delegates incoming requests directly to `app.fetch()` accompanied by the Netlify execution context object [src/adapter/netlify/handler.ts:4-10](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/netlify/handler.ts#L4-L10). Connection info helpers, such as the Lambda@Edge implementation, extract client IP addresses directly from nested event records stored within `c.env` [src/adapter/lambda-edge/conninfo.ts:11-14](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/lambda-edge/conninfo.ts#L11-L14).

Sources: [src/adapter/aws-lambda/handler.ts:252-272](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/aws-lambda/handler.ts#L252-L272)

Sources: [src/adapter/netlify/handler.ts:4-10](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/netlify/handler.ts#L4-L10)

Sources: [src/adapter/lambda-edge/conninfo.ts:11-14](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/lambda-edge/conninfo.ts#L11-L14)

```typescript
  return async (event, lambdaContext?) => {
    const processor = getProcessor(event)

    let req, requestContext
    try {
      req = processor.createRequest(event)
      requestContext = getRequestContext(event)
    } catch (error) {
      console.error('Error processing request:', error)
      const errorResponse =
        error instanceof TypeError
          ? new Response('Invalid request', { status: 400 })
          : new Response('Internal Server Error', { status: 500 })
      return processor.createResult(event, errorResponse, { isContentTypeBinary })
    }

    const res = await app.fetch(req, {
      event,
      requestContext,
      lambdaContext,
    })

    return processor.createResult(event, res, { isContentTypeBinary })
  }
}
```
Sources: [src/adapter/aws-lambda/handler.ts:252-276](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/aws-lambda/handler.ts#L252-L276)

> [!WARNING]
> Accessing `c.event` or `c.executionCtx` on platforms that do not supply a matching execution context object will throw an explicit error (`This context has no FetchEvent` or `This context has no ExecutionContext`) [src/context.ts:377-397](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L377-L397).

Sources: [src/context.ts:377-397](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts#L377-L397)

## Related

- [Request Lifecycle](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/core-engine/request-lifecycle)
- [Application Core](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/core-engine/application-core)
- [Context Storage](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/traffic-middleware/context-storage)


## Sitemap

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