This example shows how to build a counter using Durable Objects and Workers with [RPC methods](https://developers.cloudflare.com/workers/runtime-apis/rpc) that can print, increment, and decrement a `name` provided by the URL query string parameter, for example, `?name=A`.

* JavaScript

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


  // Worker
  export default {
    async fetch(request, env) {
      let url = new URL(request.url);
      let name = url.searchParams.get("name");
      if (!name) {
        return new Response(
          "Select a Durable Object to contact by using" +
            " the `name` URL query string parameter, for example, ?name=A",
        );
      }


      // Every unique ID refers to an individual instance of the Counter class that
      // has its own state. `idFromName()` always returns the same ID when given the
      // same string as input (and called on the same class), but never the same
      // ID for two different strings (or for different classes).
      let id = env.COUNTERS.idFromName(name);


      // Construct the stub for the Durable Object using the ID.
      // A stub is a client Object used to send messages to the Durable Object.
      let stub = env.COUNTERS.get(id);


      // Send a request to the Durable Object using RPC methods, then await its response.
      let count = null;
      switch (url.pathname) {
        case "/increment":
          count = await stub.increment();
          break;
        case "/decrement":
          count = await stub.decrement();
          break;
        case "/":
          // Serves the current value.
          count = await stub.getCounterValue();
          break;
        default:
          return new Response("Not found", { status: 404 });
      }


      return new Response(`Durable Object '${name}' count: ${count}`);
    },
  };


  // Durable Object
  export class Counter extends DurableObject {
    async getCounterValue() {
      let value = (await this.ctx.storage.get("value")) || 0;
      return value;
    }


    async increment(amount = 1) {
      let value = (await this.ctx.storage.get("value")) || 0;
      value += amount;
      // You do not have to worry about a concurrent request having modified the value in storage.
      // "input gates" will automatically protect against unwanted concurrency.
      // Read-modify-write is safe.
      await this.ctx.storage.put("value", value);
      return value;
    }


    async decrement(amount = 1) {
      let value = (await this.ctx.storage.get("value")) || 0;
      value -= amount;
      await this.ctx.storage.put("value", value);
      return value;
    }
  }
  ```

* TypeScript

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


  export interface Env {
    COUNTERS: DurableObjectNamespace<Counter>;
  }


  // Worker
  export default {
    async fetch(request, env) {
      let url = new URL(request.url);
      let name = url.searchParams.get("name");
      if (!name) {
        return new Response(
          "Select a Durable Object to contact by using" +
            " the `name` URL query string parameter, for example, ?name=A",
        );
      }


      // Every unique ID refers to an individual instance of the Counter class that
      // has its own state. `idFromName()` always returns the same ID when given the
      // same string as input (and called on the same class), but never the same
      // ID for two different strings (or for different classes).
      let id = env.COUNTERS.idFromName(name);


      // Construct the stub for the Durable Object using the ID.
      // A stub is a client Object used to send messages to the Durable Object.
      let stub = env.COUNTERS.get(id);


      let count = null;
      switch (url.pathname) {
        case "/increment":
          count = await stub.increment();
          break;
        case "/decrement":
          count = await stub.decrement();
          break;
        case "/":
          // Serves the current value.
          count = await stub.getCounterValue();
          break;
        default:
          return new Response("Not found", { status: 404 });
      }


      return new Response(`Durable Object '${name}' count: ${count}`);
    },
  } satisfies ExportedHandler<Env>;


  // Durable Object
  export class Counter extends DurableObject {
    async getCounterValue() {
      let value = (await this.ctx.storage.get("value")) || 0;
      return value;
    }


    async increment(amount = 1) {
      let value: number = (await this.ctx.storage.get("value")) || 0;
      value += amount;
      // You do not have to worry about a concurrent request having modified the value in storage.
      // "input gates" will automatically protect against unwanted concurrency.
      // Read-modify-write is safe.
      await this.ctx.storage.put("value", value);
      return value;
    }


    async decrement(amount = 1) {
      let value: number = (await this.ctx.storage.get("value")) || 0;
      value -= amount;
      await this.ctx.storage.put("value", value);
      return value;
    }
  }
  ```

Finally, configure your Wrangler file to include a Durable Object [binding](https://developers.cloudflare.com/durable-objects/get-started/tutorial/#5-configure-durable-object-bindings) and [migration](https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/) based on the namespace and class name chosen previously.

* wrangler.jsonc

  ```jsonc
  {
    "name": "my-counter",
    "durable_objects": {
      "bindings": [
        {
          "name": "COUNTERS",
          "class_name": "Counter"
        }
      ]
    },
    "migrations": [
      {
        "tag": "v1",
        "new_classes": [
          "Counter"
        ]
      }
    ]
  }
  ```

* wrangler.toml

  ```toml
  name = "my-counter"


  [[durable_objects.bindings]]
  name = "COUNTERS"
  class_name = "Counter"


  [[migrations]]
  tag = "v1"
  new_classes = ["Counter"]
  ```

### Related resources

* [Workers RPC](https://developers.cloudflare.com/workers/runtime-apis/rpc/)
* [Durable Objects: Easy, Fast, Correct — Choose three](https://blog.cloudflare.com/durable-objects-easy-fast-correct-choose-three/).
