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
DurableObjectNamespace
object 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
fetch
handler 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
fetch
handler can get a Durable Object instance via theCOUNTER
binding: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,});