This site is not affiliated with or endorsed by Cloudflare, Inc. It showcases deployable experiments across most Cloudflare products.
Stateful & Async

Durable Counter

Canonical Durable Objects counter - globally consistent increment/decrement with strong consistency at the edge

A minimal reference for Durable Objects: a single Counter class with persistent storage, exposed via HTTP routes. Use this pattern when you need strongly consistent state at the edge (rate limits, sessions, coordination).

API Reference

GET /counter

Returns the current counter value.

Example Request

curl "https://your-worker.workers.dev/counter"

Example Response

{ "value": 42 }

POST /counter/increment

Increments the counter by 1.

curl -X POST "https://your-worker.workers.dev/counter/increment"

POST /counter/reset

Resets the counter to 0.

curl -X POST "https://your-worker.workers.dev/counter/reset"

Use Cases

  • Learn how to define and export a Durable Object class
  • Shared counters or rate limiters across all edge locations
  • Starting point for session storage or real-time coordination
  • Understanding idFromName() for addressing a single global object

Limitations

  • Demo uses a single global counter via idFromName(); not sharded for high throughput
  • Requires a Durable Objects binding and migration
  • No authentication; any client can increment or read the counter

Use in your project

Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/durable-counter.

DependenciesNoneBindingsDurable ObjectsPlatformFetch API, Durable Objects
import type { Env } from "../types/env";import type { CounterAction, CounterValue } from "../types/counter";const COUNTER_NAME = "global";export function getCounterStub(env: Env): DurableObjectStub {  const id = env.COUNTER.idFromName(COUNTER_NAME);  return env.COUNTER.get(id);}export async function callCounter(env: Env, action: CounterAction): Promise<CounterValue> {  const stub = getCounterStub(env);  const response = await stub.fetch(`https://counter/${action}`, {    method: action === "get" ? "GET" : "POST",  });  if (!response.ok) {    throw new Error(`Counter request failed with status ${response.status}`);  }  return (await response.json()) as CounterValue;}

Deployment

Click the deploy button

Deploy to Cloudflare Workers

Test the API

curl "https://your-worker.workers.dev/counter"
curl -X POST "https://your-worker.workers.dev/counter/increment"

Local Development

cd apps/experiments/durable-counter
npm install
npm run dev

Configuration

wrangler.json declares:

  • Durable Object binding COUNTER → class Counter
  • Migration v1 registering the Counter class

Cloudflare Features Used

On this page