Skip to content

[Example]: Add Service Bindings example — auth-as-a-worker for multi-worker architectures #49

@joeblew999

Description

@joeblew999

The current Hono example runs better-auth-cloudflare as part of a single monolithic worker. This works fine for simple apps, but most production Cloudflare architectures split functionality across multiple workers. There’s currently no example showing how to run auth as a dedicated isolated worker consumed by other workers via Cloudflare Service Bindings.

Why this matters

Cloudflare’s Service Bindings allow one worker to call another directly — no public HTTP, no latency overhead, no extra egress cost. This enables an auth-as-a-service pattern inside your own Cloudflare account:

┌─────────────────┐   Service Binding   ┌──────────────────┐
│   App Worker A  │ ──────────────────► │   Auth Worker    │
├─────────────────┤                     │ (better-auth-cf) │
│   App Worker B  │ ──────────────────► │   D1 + KV        │
└─────────────────┘                     └──────────────────┘

Benefits:

  • Isolation — auth logic, D1 schema, KV namespace all owned by one worker. No other worker touches auth data directly
  • Reusability — any new worker just adds a [[services]] binding and gets session checking for free
  • Zero latency — Service Bindings are in-process, not HTTP round trips
  • Simpler security surface — auth worker is never publicly exposed, only reachable via bindings

What the example would show

wrangler.toml in the auth worker — standard, as today

wrangler.toml in a consuming worker:

[[services]]
binding = "AUTH"
service = "my-auth-worker"

Session checking in a consuming worker:

app.get("/api/protected/*", async (c) => {
  const res = await c.env.AUTH.fetch(
    new Request("https://auth/api/auth/get-session", {
      headers: c.req.raw.headers  // forward cookies
    })
  );
  const session = await res.json();
  if (!session?.user) return c.json({ error: "Unauthorized" }, 401);
  // handle request
});

Optional: typed auth client helper shared across workers via a workspace package

Why the current example doesn’t cover this

The existing Hono example co-locates the auth handler and the protected route in the same worker. That’s fine as a getting-started demo, but leaves developers to figure out the Service Bindings pattern themselves — which involves:

  • Understanding that better-auth’s handler works fine as a standalone worker with no changes
  • Knowing to forward raw request headers (including cookies) through the binding
  • Handling CORS correctly when the auth worker is internal-only
  • Knowing BETTER_AUTH_URL should point to the public-facing domain, not the internal binding URL
  • Passing ctx.waitUntil correctly so background tasks (token cleanup, session writes) complete after the response is sent across the binding

Is this blocking?

No — the pattern works today, it’s just undocumented in this repo. Developers hitting multi-worker architectures have to piece it together from Cloudflare docs + Better Auth docs + this repo’s README separately.

Related

  • Roadmap item: Durable Objects support (which would pair well with this pattern for stateful session management)
  • The README mentions Service Bindings in the Hono setup guide but doesn’t show a concrete example
  • Known gotcha: ctx.waitUntil must be forwarded through the binding call to prevent background task errors after response is sent

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions