1---
2title: Memory
3description: Run a disposable Better Auth Worker with an isolate-local memory store.
4---
5
6Use `Memory` for throwaway development and tests, not production authentication. This complete Worker example keeps records only for the lifetime of each isolate.
7
8## Install
9
10```sh
11bun add @alchemy.run/better-auth better-auth@^1.7.5
12```
13
14No optional database driver or `kysely` peer is required by the memory adapter.
15
16## Define the database layer
17
18```typescript title="src/auth-database.ts"
19import { Memory } from "@alchemy.run/better-auth/Memory";
20
21export const AuthDatabase = Memory();
22```
23
24Construct the layer once for the host, not inside `fetch`, so requests in the same isolate share its store.
25
26## Define the auth Worker
27
28```typescript title="src/worker.ts"
29import { BetterAuth } from "@alchemy.run/better-auth";
30import * as Cloudflare from "alchemy/Cloudflare";
31import * as Effect from "effect/Effect";
32import { AuthDatabase } from "./auth-database.ts";
33
34export default class AuthApi extends Cloudflare.Worker<AuthApi>()(
35 "AuthApi",
36 {
37 main: import.meta.url,
38 compatibility: { flags: ["nodejs_compat"] },
39 },
40 Effect.gen(function* () {
41 const auth = yield* BetterAuth({
42 basePath: "/api/auth",
43 emailAndPassword: { enabled: true },
44 migrate: false,
45 });
46 return { fetch: auth.fetch };
47 }).pipe(Effect.provide(AuthDatabase)),
48) {}
49```
50
51Better Auth instances remain request-scoped, while the layer retains the backing records across requests. Separate Worker isolates or Lambda instances never share these records.
52
53## Define the stack
54
55```typescript title="alchemy.run.ts"
56import * as Alchemy from "alchemy";
57import * as Cloudflare from "alchemy/Cloudflare";
58import * as Effect from "effect/Effect";
59import AuthApi from "./src/worker.ts";
60
61export default Alchemy.Stack(
62 "BetterAuthMemory",
63 {
64 providers: Cloudflare.providers(),
65 state: Alchemy.localState(),
66 },
67 Effect.gen(function* () {
68 const api = yield* AuthApi;
69 return { url: api.url.as<string>() };
70 }),
71);
72```
73
74Alchemy generates and binds a stable signing secret, persisted in local stack state. That secret does not make the memory store persistent.
75
76## Run locally
77
78```sh
79bunx alchemy dev
80```
81
82Use the printed URL rather than assuming a local port. Set `AUTH_ORIGIN` to that URL to check the auth endpoint:
83
84```sh
85curl -i "$AUTH_ORIGIN/api/auth/get-session"
86```
87
88A restart or isolate replacement loses users and sessions. Even without a restart, a deployed request routed to a different isolate may not find a previously created user.
89
90## Inspect records in tests
91
92When an in-process test needs access to the backing store, replace `src/auth-database.ts` with this file:
93
94```typescript title="src/auth-database.ts"
95import { Memory } from "@alchemy.run/better-auth/Memory";
96import type { MemoryDB } from "better-auth/adapters/memory";
97
98export const records: MemoryDB = {};
99export const AuthDatabase = Memory(records);
100```
101
102The adapter initializes missing model arrays from the auth schema, including plugins. Give independent tests independent stores; importing this module in the test process does not expose a separate Worker's in-memory records.
103
104## Migration behavior
105
106Memory has no migration support and needs no schema command. Leave `migrate` unset or false; explicitly setting it to true fails rather than pretending to migrate.
107
108Choose [D1](/better-auth/databases/cloudflare-d1) or another durable database before serving real users. See [configuration](/better-auth/guides/configuration), [migrations](/better-auth/guides/migrations), and the [`Memory` reference](/providers/betterauth/memory).