[GH-ISSUE #175] Better Auth with Cloudflare Workers #25482

Closed
opened 2026-04-17 15:43:47 -05:00 by GiteaMirror · 6 comments
Owner

Originally created by @Elliot-Alexander on GitHub (Oct 15, 2024).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/175

Hey!

Really cool project, loving what this represents for the JS Ecosystem. Based on the current structure defined in the docs and my understanding of how environment vars work and are provided for Cloudflare Workers, I'm not sure the best way to achieve compatibility between them. Interested to see if there's any thoughts in the community for setting this up.
Ideally would be done with Hono as the general framework for better compatibility with better-auth out of the gate.

Cheers!

Originally created by @Elliot-Alexander on GitHub (Oct 15, 2024). Original GitHub issue: https://github.com/better-auth/better-auth/issues/175 Hey! Really cool project, loving what this represents for the JS Ecosystem. Based on the current structure defined in the docs and my understanding of how environment vars work and are provided for Cloudflare Workers, I'm not sure the best way to achieve compatibility between them. Interested to see if there's any thoughts in the community for setting this up. Ideally would be done with Hono as the general framework for better compatibility with better-auth out of the gate. Cheers!
GiteaMirror added the locked label 2026-04-17 15:43:47 -05:00
Author
Owner

@Bekacru commented on GitHub (Oct 16, 2024):

It supports workers. For development, you can use a .dev.vars file to set environment variables, and it should automatically pick them up. Same for production. If that doesn't work, you can also define the values directly in your auth instance.

<!-- gh-comment-id:2415759057 --> @Bekacru commented on GitHub (Oct 16, 2024): It supports workers. For development, you can use a `.dev.vars` file to set environment variables, and it should automatically pick them up. Same for production. If that doesn't work, you can also define the values directly in your auth instance.
Author
Owner

@Elliot-Alexander commented on GitHub (Oct 16, 2024):

What would the access pattern look like (specifically for ES Modules format of workers)? As environment vars are only only exposed via the inbound request (see docs). Is there support declaring the auth instance inline on the request (non 'singleton') or via a function? (while still retaining support for the CLI tool functionality, migrate, generate etc)

<!-- gh-comment-id:2415885916 --> @Elliot-Alexander commented on GitHub (Oct 16, 2024): What would the access pattern look like (specifically for ES Modules format of workers)? As environment vars are only only exposed via the inbound request [(see docs)](https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/#environment-variables-in-es-modules-format). Is there support declaring the auth instance inline on the request (non 'singleton') or via a function? (while still retaining support for the CLI tool functionality, migrate, generate etc)
Author
Owner

@serban-mihai commented on GitHub (Oct 16, 2024):

It supports workers. For development, you can use a .dev.vars file to set environment variables, and it should automatically pick them up. Same for production. If that doesn't work, you can also define the values directly in your auth instance.

It doesn't pick up the .dev.vars for me, at least not while I was trying to set it up and used npx @better-auth/cli migrate against it, I tried creating a .env with the same values and it picked it up but the binding problem remains.

There is no way to avoid leaking credentials inside source control without manually injecting them into the env file at build time (through some CI/CD pipeline, I use Actions with repo secrets).

I also didn't find any way to bind a D1 database to the config since bindings are not available outside the incoming request context. I opened an issue in Hono's Discord

<!-- gh-comment-id:2417418632 --> @serban-mihai commented on GitHub (Oct 16, 2024): > It supports workers. For development, you can use a `.dev.vars` file to set environment variables, and it should automatically pick them up. Same for production. If that doesn't work, you can also define the values directly in your auth instance. It doesn't pick up the `.dev.vars` for me, at least not while I was trying to set it up and used `npx @better-auth/cli migrate` against it, I tried creating a `.env` with the same values and it picked it up but the binding problem remains. There is no way to avoid leaking credentials inside source control without manually injecting them into the env file at build time (through some CI/CD pipeline, I use Actions with repo secrets). I also didn't find any way to bind a D1 database to the config since bindings are not available outside the incoming request context. I opened an issue in [Hono's Discord](https://discord.com/channels/1011308539819597844/1296154637581160548/1296154637581160548)
Author
Owner
<!-- gh-comment-id:2480983593 --> @Bekacru commented on GitHub (Nov 17, 2024): examples - https://github.com/Bekacru/better-auth-nextjs-cf-d1-example - https://github.com/atinux/nuxthub-better-auth
Author
Owner

@zpg6 commented on GitHub (May 14, 2025):

Hello! I made an npm package called better-auth-cloudflare to ease+extend deploying Better Auth to Cloudflare, especially OpenNextJS projects. Easily integrate with D1 and KV plus you can geolocate your users. There is a demo project in the repo with helper scripts for schema generation, migrating, and deploying. Feedback and contributions are welcome

DEMO: https://better-auth-cloudflare.zpg6.workers.dev/

better-auth-cloudflare GitHub:
https://github.com/zpg6/better-auth-cloudflare

better-auth-cloudflare NPM:
https://www.npmjs.com/package/better-auth-cloudflare

<!-- gh-comment-id:2881778255 --> @zpg6 commented on GitHub (May 14, 2025): Hello! I made an npm package called` better-auth-cloudflare` to ease+extend deploying Better Auth to Cloudflare, especially OpenNextJS projects. Easily integrate with D1 and KV plus you can geolocate your users. There is a demo project in the repo with helper scripts for schema generation, migrating, and deploying. Feedback and contributions are welcome DEMO: https://better-auth-cloudflare.zpg6.workers.dev/ better-auth-cloudflare GitHub: https://github.com/zpg6/better-auth-cloudflare better-auth-cloudflare NPM: https://www.npmjs.com/package/better-auth-cloudflare
Author
Owner

@praneybehl commented on GitHub (Dec 11, 2025):

Solution for createRequire Error on Cloudflare Workers

For anyone still encountering the createRequire(import.meta.url) error with BetterAuth on Cloudflare Workers (the error: "The argument 'path' must be a file URL object, file URL string, or absolute path string. Received 'undefined'"), here's a working solution using Wrangler's module aliasing feature.

Root Cause

BetterAuth's bundled code includes createRequire(import.meta.url) from Rolldown's runtime helpers. In Cloudflare Workers, import.meta.url is undefined in the bundled output, causing the error at module initialization time.

Solution: Module Aliasing

Step 1: Create a polyfill file src/polyfills/node-module.ts:

export function createRequire(_filename: string | URL): NodeRequire {
  const req = function require(id: string): never {
    throw new Error(\`Cannot use require() in Cloudflare Workers. Module "${id}" must use ESM imports.\`);
  };
  req.resolve = (id: string): never => { throw new Error(\`Cannot use require.resolve() in Workers.\`); };
  req.resolve.paths = (_request: string): null => null;
  req.cache = {};
  req.extensions = {};
  req.main = undefined;
  return req as unknown as NodeRequire;
}

export function isBuiltin(_moduleName: string): boolean { return false; }
export function findSourceMap(_path: string): undefined { return undefined; }
export function syncBuiltinESMExports(): void {}

export default { createRequire, isBuiltin, findSourceMap, syncBuiltinESMExports };

Step 2: Add alias in wrangler.toml:

compatibility_date = "2025-09-01"
compatibility_flags = ["nodejs_compat_v2"]

[alias]
"node:module" = "./src/polyfills/node-module.ts"

Tested With

  • Wrangler 4.53.0
  • BetterAuth 1.4.6
  • Hono 4.7.0

The polyfill provides a no-op createRequire that satisfies module resolution. Since BetterAuth doesn't actually need CommonJS require() at runtime (it's just bundler artifacts), this works perfectly.

See also my comment on #1375 for the full polyfill code.

<!-- gh-comment-id:3640523795 --> @praneybehl commented on GitHub (Dec 11, 2025): ## Solution for `createRequire` Error on Cloudflare Workers For anyone still encountering the `createRequire(import.meta.url)` error with BetterAuth on Cloudflare Workers (the error: "The argument 'path' must be a file URL object, file URL string, or absolute path string. Received 'undefined'"), here's a working solution using Wrangler's module aliasing feature. ### Root Cause BetterAuth's bundled code includes `createRequire(import.meta.url)` from Rolldown's runtime helpers. In Cloudflare Workers, `import.meta.url` is undefined in the bundled output, causing the error at module initialization time. ### Solution: Module Aliasing **Step 1:** Create a polyfill file `src/polyfills/node-module.ts`: ```typescript export function createRequire(_filename: string | URL): NodeRequire { const req = function require(id: string): never { throw new Error(\`Cannot use require() in Cloudflare Workers. Module "${id}" must use ESM imports.\`); }; req.resolve = (id: string): never => { throw new Error(\`Cannot use require.resolve() in Workers.\`); }; req.resolve.paths = (_request: string): null => null; req.cache = {}; req.extensions = {}; req.main = undefined; return req as unknown as NodeRequire; } export function isBuiltin(_moduleName: string): boolean { return false; } export function findSourceMap(_path: string): undefined { return undefined; } export function syncBuiltinESMExports(): void {} export default { createRequire, isBuiltin, findSourceMap, syncBuiltinESMExports }; ``` **Step 2:** Add alias in `wrangler.toml`: ```toml compatibility_date = "2025-09-01" compatibility_flags = ["nodejs_compat_v2"] [alias] "node:module" = "./src/polyfills/node-module.ts" ``` ### Tested With - Wrangler 4.53.0 - BetterAuth 1.4.6 - Hono 4.7.0 The polyfill provides a no-op `createRequire` that satisfies module resolution. Since BetterAuth doesn't actually need CommonJS `require()` at runtime (it's just bundler artifacts), this works perfectly. See also my comment on #1375 for the full polyfill code.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#25482