Durable Object
Create, bind, and use Cloudflare Durable Objects in your Worker applications. Learn how to implement stateful microservices with persistent storage in Cloudflare Workers.
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,});