Devflare Docs
Runtime helpers Devflare

Think in events first, then let AsyncLocalStorage carry the active context through the handler trail

Devflare-managed entrypoints create a rich surface event, store , , , , , and the original event in , then expose that state through helpers such as , , , and the , , , and runtime proxies inside the same handler trail.

The public story is still event-first, but this is also the page for the helper APIs that depend on that model: , , , , , , and the , , , and exports from . Your handler gets a rich event object, and Devflare stores a matching in Node so those helpers can recover the active surface without threading the event through every layer.

Context carrier
Node under Devflare-managed entrypoints
Main helpers
, , , , , , and
Stored shape
, , , , , and the original event object
Mutable lane
/
Failure mode
Strict runtime helpers throw outside an active handler trail

The AsyncLocalStorage-powered helpers are the whole point of this page

If you landed here because or worked in one place and exploded in another, this page should say that plainly: those APIs all depend on the same AsyncLocalStorage-backed .

That includes the per-surface getters, the generic helper, and the runtime exports that feel global in app code but are really reading the active request or job context under the hood.

Helper familyExamplesWhat AsyncLocalStorage gives them
Per-surface getters, , , , Return the current rich event after verifying the active surface type; returns instead of throwing.
Generic context getterReturns the active stored context shape when one exists and throws when code is running outside an active handler trail.
Readonly runtime proxies, , Read the active environment bindings, execution context, or original event from the current AsyncLocalStorage store without parameter threading.
Mutable runtime proxyReads and writes the per-request or per-job mutable storage object attached to the active context.

A practical reading guide

If the question in your head is “when can I safely call or read without passing the event around?”, the rest of this page is answering exactly that.

Start with event-first handlers and let helpers discover the active event later

Event-first handlers keep runtime state explicit at the boundary and still let deeper helpers recover the current event later when plumbing it through every function call would be pure ceremony. That is the everyday job for helpers like and .

In normal application code you should not need to establish AsyncLocalStorage context manually. Devflare already does that for generated worker entrypoints, middleware, route dispatch, Durable Object wrappers, the dev server, and the built-in test helpers.

Use the explicit event at the boundary and a getter inside the helper

This keeps the handler honest while still letting helper code read the active request and shared locals later in the same call trail.

Devflare stores a full , not just one request reference

Under the hood, Devflare creates . The stored value is richer than “the current request”: it keeps the active environment bindings, the current execution context or Durable Object state, an optional request, mutable locals, the runtime surface type, and the original event object.

That design is why the higher-level runtime APIs can stay small. Per-surface getters return the stored event when the active surface matches. The generic proxies read the same store without caring whether the call trail came from fetch, queue, scheduled, email, tail, or Durable Objects.

The original event object is still preserved

Devflare does not discard the richer surface event after extracting a request or context. The original event stays on , which is what the per-surface getters read later.

Simplified shape of the value Devflare puts into AsyncLocalStorage

Code sample type: ts

Devflare first creates a rich event, then runs the handler trail inside AsyncLocalStorage

For fetch, queue, scheduled, email, tail, and Durable Object surfaces, Devflare first creates a rich event object using helpers such as , , or the Durable Object event builders. It then builds a from that event and runs the handler trail inside .

The same mechanism is reused by generated worker entrypoints, request-wide middleware, route resolution, Durable Object wrappers, the dev server, and helpers such as , , , , and . That shared mechanism is why runtime helpers feel consistent in app code and test code.

  1. 1

    Devflare builds the rich event object for the active surface.

  2. 2

    It creates a from , , , , , and the original event object.

  3. 3

    It runs middleware, route resolution, or the surface handler inside with that context.

  4. 4

    Deeper helpers call getters or proxies, which read the current store instead of receiving the event manually.

  5. 5

    When the handler trail ends, the strict runtime helpers stop pretending context still exists.

One store is what keeps runtime behavior consistent

If a helper works in the dev server but not in tests, or vice versa, that is a bug. Devflare intentionally drives both through the same AsyncLocalStorage-backed context model.

The important part of `runWithEventContext()` is small on purpose

Code sample type: ts

Getters and proxies are just different ways of reading the same store

Pass the event explicitly at the top of the stack. Reach for getters or proxies only when you are deeper in the same handler trail and threading that event downward would make the code noisier than the value it adds.

This is also why strict runtime helpers throwing outside context is healthy: it stops top-level module code and random utility calls from pretending they are running inside a request when they are not.

APIWhat it readsFailure behaviorMutation
Handler parametersThe explicit event object Devflare passes to the handler boundary.No lookup needed at the boundary. is mutable.
Per-surface getters like The stored after Devflare verifies the active surface type.Throws , while returns .Readonly event view.
The full active object from the current AsyncLocalStorage store.Throws outside an active handler trail.Use this mostly for debugging or advanced infrastructure helpers.
, , proxies through readonly proxy wrappers.Property access throws outside an active handler trail.Readonly.
proxy through the mutable context proxy.Property access throws outside an active handler trail.Mutable and shared with .

A simple rule

Use explicit handler parameters first, getters second, proxies third, and mutable only for data that truly belongs to the current request or job.

The AsyncLocalStorage model covers more than fetch

Worker surfaces expose as the current . Durable Object surfaces expose as the current , and Devflare also aliases that same value as for clarity.

For fetch and Durable Object fetch, Devflare augments the actual instance. For queue, scheduled, email, tail, and Durable Object WebSocket surfaces, it augments the native carrier object instead of replacing it with a fantasy wrapper. That is why the event-first API still feels like Cloudflare instead of a new platform.

This is why the runtime feels consistent across local dev, tests, route middleware, and Durable Object wrappers once you learn the model once.

SurfaceEvent shapeGetter
HTTP worker
Queue consumer
Scheduled handler
Inbound email
Tail handler
Durable Object fetch
Durable Object alarm
Durable Object WebSocket message / close / errorDedicated WebSocket event types, ,

is the mutable storage lane, and it is isolated per context

Use for auth state, derived request data, request ids, or other values that belong to the current request or job and should be shared across middleware or helper layers.

Within one handler trail, and point at the same underlying object. Across requests and jobs, each context gets a fresh locals object so state does not bleed between invocations.

Mutate , not the readonly proxies

, , and are readonly runtime views. If you need shared mutable state, put it on instead of trying to assign back into the underlying context objects.

Write to `event.locals`, read from `locals` later in the same trail

Context is not available everywhere, and that is intentional

  • Module top-level code runs at cold start, not inside a request or job, so strict runtime helpers are unavailable there.
  • Callbacks that run after the handler trail ends should take explicit inputs instead of assuming context is still alive.
  • Timer callbacks like and are outside the normal Devflare-managed handler trail.
  • Per-surface getters and throw , while proxy property access such as or throws naming the missing property.
  • If you are unsure whether the matching surface is active, prefer accessors such as over catching thrown errors.
  • If runtime context access fails unexpectedly while bypassing Devflare-generated config or harnesses, verify that the Worker still includes the AsyncLocalStorage compatibility flags Devflare normally adds for you.

The fix is usually simpler than the error feels

Move the context access inside the handler, middleware, or helper that is called from that handler trail. If there is no active trail, take explicit inputs instead of hoping context exists.

and are advanced helpers, not normal app code

By the time you are considering these helpers, the normal app-facing story should already be working: handlers, middleware, generated entrypoints, and establish context for you. These APIs exist for runtime and test infrastructure that must preserve or synthesize that context deliberately.

preserves an existing rich event object. is the lower-level compatibility helper: it creates fresh locals, synthesizes a default event with , and then stores that event in AsyncLocalStorage before running your function.

Do not reach for the escape hatch by habit

If you are writing app code instead of runtime or test infrastructure, pass the event into your handler and let Devflare establish the context automatically.

Previous

Runtime & deploy settings

Use config for account context, compatibility posture, assets, deployment routes, WebSocket proxy rules, migrations, observability, limits, and preview cron behavior instead of rediscovering those settings in scripts later.

Next

sequence(...)

Use from when broad HTTP concerns must wrap route resolution or another fetch handler in a clear top-to-bottom order.