Skip to content

Invoking methods

Invoking methods on a Durable Object

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.

Invoke RPC methods

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 Object
export class MyDurableObject extends DurableObject {
constructor(ctx, env) {
super(ctx, env);
}
async sayHello() {
return "Hello, World!";
}
}
// Worker
export 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);
},
};

Refer to Build a Counter for a complete example.

Invoking the fetch handler

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 Object
export class MyDurableObject extends DurableObject {
constructor(ctx, env) {
super(ctx, env);
}
async fetch(request) {
return new Response("Hello, World!");
}
}
// Worker
export 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;
},
};

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 Object
export 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 });
}
}
}
// Worker
export 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;
},
};