Tutorial
This guide will instruct you through:
- Writing a Durable Object class.
- Writing a Worker which invokes methods on a Durable Object.
- Deploying a Durable Object.
If you wish to learn more about Durable Objects, refer to What are Durable Objects?.
- Sign up for a Cloudflare account ↗.
- Install
Node.js↗.
Node.js version manager
Use a Node version manager like Volta ↗ or nvm ↗ to avoid permission issues and change Node.js versions. Wrangler, discussed later in this guide, requires a Node version of 16.17.0 or later.
To enable Durable Objects, you will need to purchase the Workers Paid plan:
- Log in to the Cloudflare dashboard ↗, and select your account.
- Go to Workers & Pages > Plans.
- Select Purchase Workers Paid and complete the payment process to enable Durable Objects.
Durable Objects are accessed from a Worker.
To create a Worker project, run:
npm create cloudflare@latest -- durable-object-starterpnpm create cloudflare@latest durable-object-starteryarn create cloudflare durable-object-starterRunning create cloudflare@latest will install Wrangler, the Workers CLI. You will use Wrangler to test and deploy your project.
For setup, select the following options:
- For What would you like to start with?, choose
Hello World example. - For Which template would you like to use?, choose
Hello World Worker using Durable Objects. - For Which language do you want to use?, choose
JavaScript / TypeScript. - For Do you want to use git for version control?, choose
Yes. - For Do you want to deploy your application?, choose
No(we will be making some changes before deploying).
This will create a new directory, which will include either a src/index.js or src/index.ts file to write your code and a wrangler.jsonc configuration file.
Move into your new directory:
cd durable-object-starterDurable Objects are defined by a exporting a standard JavaScript class which extends from the DurableObject base class.
Your MyDurableObject class will have a constructor with two parameters. The first parameter, state, passed to the class constructor contains state specific to the Durable Object, including methods for accessing storage. The second parameter, env, contains any bindings you have associated with the Worker when you uploaded it.
import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject { constructor(state, env) {}}import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject { constructor(state: DurableObjectState, env: Env) {}}Workers can invoke public methods defined on a Durable Object via Remote Procedure Call (RPC).
The sayHello method demonstrates this capability:
import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject { constructor(state, env) {}
async sayHello() { return "Hello, World!"; }}import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject { constructor(state: DurableObjectState, env: Env) {}
async sayHello(): Promise<string> { return "Hello, World!"; }}As mentioned previously, methods on a Durable Object class are invoked by a Worker. This is done by creating an ID refering to an instance of the Durable Object class, getting a stub that refers to a particular instance of a Durable Object class, and invoking methods on that stub.
The fetch handler should look like the following:
// Workerexport default { async fetch(request, env) { // Every unique ID refers to an individual instance of the Durable Object class const id = env.MY_DURABLE_OBJECT.idFromName("foo");
// A stub is a client used to invoke methods on the Durable Object const stub = env.MY_DURABLE_OBJECT.get(id);
// Methods on the Durable Object are invoked via the stub const rpcResponse = await stub.sayHello();
return new Response(rpcResponse); },};// Workerexport default { async fetch(request, env, ctx): Promise<Response> { // Every unique ID refers to an individual instance of the Durable Object class const id = env.MY_DURABLE_OBJECT.idFromName("foo");
// A stub is a client used to invoke methods on the Durable Object const stub = env.MY_DURABLE_OBJECT.get(id);
// Methods on the Durable Object are invoked via the stub const rpcResponse = await stub.sayHello();
return new Response(rpcResponse); },} satisfies ExportedHandler<Env>;To allow a Worker to invoke methods on a Durable Object, the Worker must have a Durable Object binding in the project's Wrangler configuration file. The binding is configured to use a particular Durable Object class.
{ "durable_objects": { "bindings": [ { "name": "MY_DURABLE_OBJECT", "class_name": "MyDurableObject" } ] }}[[durable_objects.bindings]]name = "MY_DURABLE_OBJECT"class_name = "MyDurableObject"The [[durable_objects.bindings]] section contains the following fields:
name- Required. The binding name to use within your Worker.class_name- Required. The class name you wish to bind to.script_name- Optional. The name of the Worker if the Durable Object is external to this Worker.environment- Optional. The environment of thescript_nameto bind to.
Refer to Wrangler Configuration for more detail.
A migration is a mapping process from a class name to a runtime state. You perform a migration when creating a new Durable Object class, or when renaming, deleting or transferring an existing Durable Object class.
Migrations are performed through the [[migrations]] configurations key in your Wrangler file.
The Durable Object migration to create a new Durable Object class will look like the following in your Worker's Wrangler file:
{ "migrations": [ { "tag": "v1", "new_classes": [ "MyDurableObject" ] } ]}[[migrations]]tag = "v1" # Should be unique for each entrynew_classes = ["MyDurableObject"] # Array of new classesA Durable Object class can only have a single storage type, which cannot be changed after the Durable Object class is created.
To configure SQL storage and API, replace new_classes with new_sqlite_classes in your Worker's Wrangler file:
{ "migrations": [ { "tag": "v1", "new_sqlite_classes": [ "MyDurableObject" ] } ]}[[migrations]]tag = "v1" # Should be unique for each entrynew_sqlite_classes = ["MyDurableObject"] # Array of new classesRefer to Durable Objects migrations to learn more about the migration process.
To test your Durable Object locally, run wrangler dev:
npx wrangler devIn your console, you should see aHello world string returned by the Durable Object.
To deploy your Durable Object Worker:
npx wrangler deployOnce deployed, you should be able to see your newly created Durable Object Worker on the Cloudflare dashboard ↗, Workers & Pages > Overview.
Preview your Durable Object Worker at <YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev.
By finishing this tutorial, you have successfully created, tested and deployed a Durable Object.
- Send requests to Durable Objects
- Miniflare ↗ - Helpful tools for mocking and testing your Durable Objects.