Skip to content

Use the Alarms API

Use the Durable Objects Alarms API to batch requests to a Durable Object.

This example implements an alarm() handler that wakes the Durable Object once every 10 seconds to batch requests to a single Durable Object. The alarm() handler will delay processing until there is enough work in the queue.

// Worker
export default {
async fetch(request, env) {
let id = env.BATCHER.idFromName("foo");
return await env.BATCHER.get(id).fetch(request);
},
};
const SECONDS = 10;
// Durable Object
export class Batcher {
constructor(state, env) {
this.state = state;
this.storage = state.storage;
this.state.blockConcurrencyWhile(async () => {
let vals = await this.storage.list({ reverse: true, limit: 1 });
this.count = vals.size == 0 ? 0 : parseInt(vals.keys().next().value);
});
}
async fetch(request) {
this.count++;
// If there is no alarm currently set, set one for 10 seconds from now
// Any further POSTs in the next 10 seconds will be part of this batch.
let currentAlarm = await this.storage.getAlarm();
if (currentAlarm == null) {
this.storage.setAlarm(Date.now() + (1000 * SECONDS));
}
// Add the request to the batch.
await this.storage.put(this.count, await request.text());
return new Response(JSON.stringify({ queued: this.count }), {
headers: {
"content-type": "application/json;charset=UTF-8",
},
});
}
async alarm() {
let vals = await this.storage.list();
await fetch("http://example.com/some-upstream-service", {
method: "POST",
body: Array.from(vals.values()),
});
await this.storage.deleteAll();
this.count = 0;
}
}

The alarm() handler will be called once every 10 seconds. If an unexpected error terminates the Durable Object, the alarm() handler will be re-instantiated on another machine. Following a short delay, the alarm() handler will run from the beginning on the other machine.

Finally, configure your wrangler.toml file to include a Durable Object binding and migration based on the namespace and class name chosen previously.

wrangler.toml
name = "durable-object-alarm"
[[durable_objects.bindings]]
name = "BATCHER"
class_name = "Batcher"
[[migrations]]
tag = "v1"
new_classes = ["Batcher"]