Cloudflare Workers
The Cloudflare adapter exports a Workers module entrypoint — the canonical export default { fetch } shape. Service Worker style (addEventListener("fetch", ...)) is no longer recommended; the adapter does not emit it.
When to choose Workers
- You want global, low-latency execution without managing regions yourself.
- You can live without raw TCP sockets (Workers Hyperdrive solves Postgres).
- You want bindings (KV, R2, D1, Durable Objects, Queues) instead of standalone services.
Scaffold
Worker entrypoint (no bindings)
If you don't need env bindings or the Worker ExecutionContext, toFetchHandler is a one-liner. It returns the { fetch }object Workers expect as the default export — do not wrap it again.
wrangler.jsonc
Cloudflare now recommends wrangler.jsonc over wrangler.toml for new projects; both are still supported. The single nodejs_compatflag is all you need on a recent compatibility date — there's no separate nodejs_compat_v2 to add.
Deploy
wrangler publish was renamed to wrangler deployin 2024. Don't use the old name; some CI templates still reference it.
Bindings (env)
toFetchHandler(app) only forwards the Request. To expose Worker bindings (KV, R2, D1, Durable Objects, Queues, Hyperdrive, secrets) to your handlers, write the module-format export by hand and inject the bindings into the app with app.decorate(...)— that's how DaloyJS makes runtime values available on ctx.state inside every handler.
Inside any route handler, read the binding from ctx.state.env (the key you passed to decorate):
Gotchas
- No raw TCP. Use Hyperdrivefor Postgres/MySQL, or HTTP drivers like Neon's serverless driver, PlanetScale's
@planetscale/database, or Turso/libSQL. See Database hosting. - No filesystem — use multipart uploads with R2, not
node:fs. - For background work, decorate the app with a
waitUntilwrapper (see the bindings example above) —toFetchHandleralone does not forward the WorkerExecutionContext.