---
description: Call RPC methods or send fetch requests to Durable Objects using stubs from a Worker.
title: Invoke methods
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/durable-objects/llms.txt  
> Use this file to discover all available pages before exploring further.

# Invoke methods

Last updated Aug 24, 2026|Copy as Markdown|[View as Markdown](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/durable-objects/best-practices/create-durable-object-stubs-and-send-requests/index.md)|[Agent setup](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/agent-setup/)

## Invoking methods on a Durable Object

All new projects and existing projects with a compatibility date greater than or equal to [2024-04-03](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/configuration/compatibility-flags/#durable-object-stubs-and-service-bindings-support-rpc) should prefer to invoke [Remote Procedure Call (RPC)](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/runtime-apis/rpc/) methods defined on a Durable Object class.

Projects requiring HTTP request/response flows or legacy projects can continue to invoke the `fetch()` handler on the Durable Object class.

### 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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/runtime-apis/rpc/), which you can call using a [DurableObjectStub](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/durable-objects/api/stub) from a Worker.

All RPC calls are [asynchronous](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/), accept and return [serializable types](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/runtime-apis/rpc/), and [propagate exceptions](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/runtime-apis/rpc/error-handling/) to the caller without a stack trace. Refer to [Workers RPC](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/runtime-apis/rpc/) for complete details.

```js
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) {
		// A stub is a client used to invoke methods on the Durable Object
		const stub = env.MY_DURABLE_OBJECT.getByName("foo");

		// Methods on the Durable Object are invoked via the stub
		const rpcResponse = await stub.sayHello();

		return new Response(rpcResponse);
	},
};
```

```ts
import { DurableObject } from "cloudflare:workers";

export interface Env {
	MY_DURABLE_OBJECT: DurableObjectNamespace<MyDurableObject>;
}

// Durable Object
export class MyDurableObject extends DurableObject {
	constructor(ctx: DurableObjectState, env: Env) {
		super(ctx, env);
	}

	async sayHello(): Promise<string> {
		return "Hello, World!";
	}
}

// Worker
export default {
	async fetch(request, env) {
		// A stub is a client used to invoke methods on the Durable Object
		const stub = env.MY_DURABLE_OBJECT.getByName("foo");

		// Methods on the Durable Object are invoked via the stub
		const rpcResponse = await stub.sayHello();

		return new Response(rpcResponse);
	},
} satisfies ExportedHandler<Env>;
```

Note

With RPC, the `DurableObject` superclass defines `ctx` and `env` as class properties. What was previously called `state` is now called `ctx` when you extend the `DurableObject` class. The name `ctx` is adopted rather than `state` for the `DurableObjectState` interface to be consistent between `DurableObject` and `WorkerEntrypoint` objects.

Refer to [Build a Counter](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/durable-objects/examples/build-a-counter/) for a complete example.

### Invoking the `fetch` handler

If your project is stuck on a compatibility date before [2024-04-03](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/configuration/compatibility-flags/#durable-object-stubs-and-service-bindings-support-rpc), or has the need to send a [Request](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/runtime-apis/request/) object and return a `Response` object, then you should send requests to a Durable Object via the fetch handler.

```js
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) {
		// A stub is a client used to invoke methods on the Durable Object
		const stub = env.MY_DURABLE_OBJECT.getByName("foo");

		// Methods on the Durable Object are invoked via the stub
		const response = await stub.fetch(request);

		return response;
	},
};
```

```ts
import { DurableObject } from "cloudflare:workers";

export interface Env {
	MY_DURABLE_OBJECT: DurableObjectNamespace<MyDurableObject>;
}

// Durable Object
export class MyDurableObject extends DurableObject {
	constructor(ctx: DurableObjectState, env: Env) {
		super(ctx, env);
	}

	async fetch(request: Request): Promise<Response> {
		return new Response("Hello, World!");
	}
}

// Worker
export default {
	async fetch(request, env) {
		// A stub is a client used to invoke methods on the Durable Object
		const stub = env.MY_DURABLE_OBJECT.getByName("foo");

		// 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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/runtime-apis/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.

```js
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) {
		// A stub is a client used to invoke methods on the Durable Object
		const stub = env.MY_DURABLE_OBJECT.getByName("foo");

		// Invoke the fetch handler on the Durable Object stub
		let response = await stub.fetch("http://do/hello?name=World");

		return response;
	},
};
```

```ts
import { DurableObject } from "cloudflare:workers";

export interface Env {
	MY_DURABLE_OBJECT: DurableObjectNamespace<MyDurableObject>;
}

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

// Worker
export default {
	async fetch(_request, env, _ctx) {
		// A stub is a client used to invoke methods on the Durable Object
		const stub = env.MY_DURABLE_OBJECT.getByName("foo");

		// Invoke the fetch handler on the Durable Object stub
		let response = await stub.fetch("http://do/hello?name=World");

		return response;
	},
} satisfies ExportedHandler<Env>;
```

Was this helpful?

YesNo

## On this page

[![](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/durable-objects/best-practices/create-durable-object-stubs-and-send-requests/#page","headline":"Invoke methods · Cloudflare Durable Objects docs","description":"Call RPC methods or send fetch requests to Durable Objects using stubs from a Worker.","url":"https://developers.cloudflare.com/durable-objects/best-practices/create-durable-object-stubs-and-send-requests/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["RPC"]}
```
