Invoking methods
All new projects and existing projects with a compatibility date greater than or equal to 2024-04-03
should prefer to invoke Remote Procedure Call (RPC) methods defined on a Durable Object class. Legacy projects can continue to invoke the fetch
handler on the Durable Object class indefinitely.
By writing a Durable Object class which inherits from the built-in type DurableObject
, public methods on the Durable Objects class are exposed as RPC methods, which you can call using a DurableObjectStub from a Worker.
All RPC calls are asynchronous, accept and return serializable types, and propagate exceptions to the caller without a stack trace. Refer to Workers RPC for complete details.
import { DurableObject } from "cloudflare:workers";
// Durable Objectexport class MyDurableObject extends DurableObject { constructor(ctx, env) { super(ctx, env); }
async sayHello() { return "Hello, World!"; }}
// 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); },};
import { DurableObject } from "cloudflare:workers";
export interface Env { MY_DURABLE_OBJECT: DurableObjectNamespace<MyDurableObject>;}
// Durable Objectexport class MyDurableObject extends DurableObject { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); }
async sayHello(): Promise<string> { return "Hello, World!"; }}
// 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); },} satisfies ExportedHandler<Env>;
Refer to Build a Counter for a complete example.
If your project is stuck on a compatibility date before 2024-04-03
, or has the need to send a Request
object and return a Response
object, then you should send requests to a Durable Object via the fetch handler.
import { DurableObject } from "cloudflare:workers";
// Durable Objectexport class MyDurableObject extends DurableObject { constructor(ctx, env) { super(ctx, env); }
async fetch(request) { return new Response("Hello, World!"); }}
// 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 response = await stub.fetch(request);
return response; },};
import { DurableObject } from "cloudflare:workers";
export interface Env { MY_DURABLE_OBJECT: DurableObjectNamespace<MyDurableObject>;}
// Durable Objectexport class MyDurableObject extends DurableObject { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); }
async fetch(request: Request): Promise<Response> { return new Response("Hello, World!"); }}
// 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 response = await stub.fetch(request);
return response; },} satisfies ExportedHandler<Env>;
The URL
associated with the Request
object passed to the fetch()
handler of your Durable Object must be a well-formed URL, but does not have to be a publicly-resolvable hostname.
Without RPC, customers frequently construct requests which corresponded to private methods on the Durable Object and dispatch requests from the fetch
handler. RPC is obviously more ergonomic in this example.
import { DurableObject } from "cloudflare:workers";
// Durable Objectexport class MyDurableObject extends DurableObject { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); }
private hello(name) { return new Response(`Hello, ${name}!`); }
private goodbye(name) { return new Response(`Goodbye, ${name}!`); }
async fetch(request) { const url = new URL(request.url); let name = url.searchParams.get("name"); if (!name) { name = "World"; }
switch (url.pathname) { case "/hello": return this.hello(name); case "/goodbye": return this.goodbye(name); default: return new Response("Bad Request", { status: 400 }); } }}
// Workerexport default { async fetch(_request, env, _ctx) { // 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);
// Invoke the fetch handler on the Durable Object stub let response = await stub.fetch("http://do/hello?name=World");
return response; },};
import { DurableObject } from "cloudflare:workers";
export interface Env { MY_DURABLE_OBJECT: DurableObjectNamespace<MyDurableObject>;}
// Durable Objectexport class MyDurableObject extends DurableObject { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); }
private hello(name: string) { return new Response(`Hello, ${name}!`); }
private goodbye(name: string) { return new Response(`Goodbye, ${name}!`); }
async fetch(request: Request): Promise<Response> { const url = new URL(request.url); let name = url.searchParams.get("name"); if (!name) { name = "World"; }
switch (url.pathname) { case "/hello": return this.hello(name); case "/goodbye": return this.goodbye(name); default: return new Response("Bad Request", { status: 400 }); } }}
// Workerexport default { async fetch(_request, env, _ctx) { // 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);
// Invoke the fetch handler on the Durable Object stub let response = await stub.fetch("http://do/hello?name=World");
return response; },} satisfies ExportedHandler<Env>;