Durable Object
This guide explains how to create, bind and use Cloudflare Durable Objects within your Worker scripts.
-
Create a Durable Object
At a bare minimum, you need to create a
DurableObjectNamespaceobject as a stable reference to your Durable Object namespace.import { DurableObjectNamespace } from "alchemy/cloudflare";const counter = DurableObjectNamespace("counter", {className: "Counter",// whether you want a sqllite db per DO (usually yes!)sqlite: true,}); -
Bind to a Worker
Then bind it to your Worker:
export const worker = await Worker("Worker", {name: "my-worker",entrypoint: "./index.ts"bindings: {// bind the Durable Object namespace to your WorkerCOUNTER: counter,},}); -
Implement the Durable Object Class
To use this Durable Object, our Worker script must include a class for the Durable Object and then some code in the
fetchhandler to interact with it.import type { worker } from "./alchemy.run";import { DurableObject } from "cloudflare:workers";export class Counter extends DurableObject {declare env: typeof worker.Env;private count: number;constructor(ctx: DurableObjectState, env: typeof worker.Env) {super(ctx, env);// Initialize count from storage or 0this.count = Number(this.ctx.storage.kv.get('count') || 0);}async fetch(request: Request) {const url = new URL(request.url);const path = url.pathname;if (path === "/increment") {this.count++;} else if (path === "/decrement") {this.count--;}// Update count in storagethis.ctx.storage.kv.put('count', this.count.toString());return Response.json({ count: this.count });}} -
Call from a Worker
Now, our
fetchhandler can get a Durable Object instance via theCOUNTERbinding:import { env } from "cloudflare:workers";export default {async fetch(request: Request) {const url = new URL(request.url);// Create an ID for the Counter (different IDs = different Counter instances)const id = env.COUNTER.idFromName("A");// Get a stub for the Counter instanceconst stub = env.COUNTER.get(id);// Forward the request to the Durable Objectreturn stub.fetch(request);},}; -
(Optional) Rename the Class
Alchemy takes care of migrations automatically when you rename the class name.
import { DurableObjectNamespace } from "alchemy/cloudflare";const counter = DurableObjectNamespace("counter", {className: "Counter",className: "MyCounter",// whether you want a sqllite db per DO (usually yes!)sqlite: true,});