1# Cloudflare Durable Object SQL
2
3A Worker with a separate SQLite users table for each named Durable Object, using Drizzle and checked-in SQL.
4
5## Run locally
6
7Start at the repository root; run subsequent commands from the example directory.
8
9```sh
10pnpm install
11cd examples/cloudflare-durable-object-sql
12pnpm dev
13```
14
15Use the Worker URL printed by Alchemy:
16
17```sh
18URL='http://localhost:<port>'
19
20curl -X POST "$URL/objects/team-a/users" \
21 -H 'content-type: application/json' \
22 -d '{"name":"Ada"}'
23# {"user":{"id":1,"name":"Ada"}}
24
25curl "$URL/objects/team-a/users"
26# {"users":[{"id":1,"name":"Ada"}]}
27
28curl "$URL/objects/team-b/users"
29# {"users":[]}
30```
31
32## Deploy
33
34Configure Cloudflare credentials if needed, then deploy:
35
36```sh
37pnpm exec alchemy profile edit --add Cloudflare
38pnpm deploy
39```
40
41Keep `.alchemy` for subsequent deployments and cleanup.
42
43## Migrations
44
45The example already includes `drizzle/20260919000000_create_users/migration.sql`:
46
47```sql
48CREATE TABLE users (
49 id INTEGER PRIMARY KEY AUTOINCREMENT,
50 name TEXT NOT NULL
51);
52```
53
54`src/Users.ts` captures the SQL during construction and applies it when each object activates:
55
56```ts
57Effect.gen(function* () {
58 const migrations = yield* Cloudflare.SqlMigrations("./drizzle");
59
60 return Effect.gen(function* () {
61 const db = yield* Drizzle.DurableObject({ migrations, relations });
62 return { listUsers: () => db.select().from(users) };
63 });
64});
65```
66
67## Schema changes
68
69Add new SQL files with your schema changes; keep applied files unchanged. Restart `pnpm dev` after SQL edits.
70
71```sh
72git add src/schema.ts drizzle
73git commit -m "Add schema migration"
74pnpm deploy
75```
76
77## Custom history table
78
79```ts
80const migrations = yield* Cloudflare.SqlMigrations({
81 dir: "./drizzle",
82 table: "app_migrations", // default: __alchemy_migrations
83});
84```
85
86## Without Drizzle
87
88In the inner instance Effect:
89
90```ts
91yield* migrations.apply().pipe(Effect.orDie);
92```
93
94See the [migration guide](https://alchemy.run/sql/drizzle/migrations#durable-object-migrations) for drizzle-kit setup, rollback behavior, and existing migration history.
95
96## Integration test
97
98Uses real Cloudflare resources and destroys the test deployment afterward.
99
100```sh
101pnpm test
102```
103
104## Clean up
105
106Deletes the Worker and all Durable Object data; keeps the SQL files in Git.
107
108```sh
109pnpm destroy
110```