Deploy to Cloudflare Workers

Use Bun as the package manager and local toolchain for Workers while respecting the workerd runtime boundary

Last updated on

Be clear about Bun's role first

Once deployed, your code runs on Cloudflare's workerdnot Bun. Bun's jobs here are: package management (bun install), local tooling (bunx wrangler), and tests (bun test for pure logic). Write this boundary into your agent rules, or it will put Bun.* APIs into code that ships to the edge.

1. Create the project

bun create cloudflare@latest my-worker
cd my-worker
bun install

2. Configure

wrangler.jsonc
{
  "name": "my-worker",
  "main": "src/index.ts",
  "compatibility_date": "2026-08-02",
  "compatibility_flags": ["nodejs_compat"]
}

nodejs_compat makes workerd provide a subset of Node APIs — a subset, not full Node. Code that only uses Web standard APIs can drop the flag.

src/index.ts
export default {
  async fetch(request: Request): Promise<Response> {
    return Response.json({ ok: true, runtime: 'workerd' });
  },
};

3. Verify locally and deploy

bunx wrangler dev          # runs locally in workerd, close to production behavior
bunx wrangler secret put API_KEY   # secrets never enter source or wrangler config
bunx wrangler deploy

Because wrangler dev already executes in workerd, "works locally" is a meaningful signal here — but bindings like KV, D1, and Queues still need separate setup and drills per Cloudflare's docs.

Boundaries

  • No Bun.serve, Bun.file, bun:sqlite, or other Bun-specific APIs in shipped code; shared packages stick to Web standards (fetch, Request/Response, Web Crypto).
  • nodejs_compat coverage is partial; packages relying on Node-specific behavior must be tested under wrangler dev.
  • CPU time, memory, and subrequest limits apply; for long AI streaming responses prefer ReadableStream and load-test on your actual plan.
  • bun test suits pure logic; binding-dependent behavior belongs in workerd via the official Workers testing tools (e.g. vitest-pool-workers).

Acceptance

  1. wrangler dev and the deployed Worker behave identically;
  2. No Bun.* references reach the deployed bundle;
  3. All secrets are injected via wrangler secret;
  4. Streaming responses and maximum execution times verified on the target plan.

Official references: Cloudflare Workers, Wrangler configuration, Workers Node.js compatibility.