| name | realtime |
| description | Build realtime Cloudflare applications using Durable Objects with WebSockets for data realtime and Cloudflare Realtime/WebRTC for audio and video. Use for chat rooms, multiplayer, collaboration, presence, live dashboards, and media-session routing.
|
| compatibility | Cloudflare Workers TypeScript projects using Wrangler; verify current Cloudflare APIs, limits, and pricing before production use. |
| metadata | {"source":"Architecting on Cloudflare plus official Cloudflare Developer Platform docs","generated":"2026-04-28"} |
Realtime
Use this skill for realtime application design. Separate data realtime from media realtime before writing code.
Data vs media
- Data realtime: chat, presence, multiplayer state, collaborative editing, live dashboards. Prefer Durable Objects + WebSockets.
- Media realtime: audio/video/screen share over WebRTC. Prefer Cloudflare Realtime/SFU patterns.
- Do not use WebSockets as the primary transport for audio/video media unless you have a very specific reason.
Durable Object room model
A room-like Durable Object serializes membership and broadcasts messages to connected clients.
Worker route /rooms/:id/ws
-> derive room ID from URL and authenticated tenant
-> env.ROOM.getByName(`tenant:${tenantId}:room:${roomId}`)
-> DO accepts WebSocket and stores/broadcasts room events
WebSocket handler sketch
import { DurableObject } from "cloudflare:workers";
export class Room extends DurableObject<Env> {
private sockets = new Set<WebSocket>();
async fetch(request: Request): Promise<Response> {
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
server.accept();
this.sockets.add(server);
server.addEventListener("message", (event) => {
const text = typeof event.data === "string" ? event.data : "";
for (const socket of this.sockets) {
if (socket.readyState === WebSocket.OPEN) socket.send(text);
}
});
server.addEventListener("close", () => this.sockets.delete(server));
server.addEventListener("error", () => this.sockets.delete(server));
return new Response(null, { status: 101, webSocket: client });
}
}
Validate this sketch against current hibernation/WebSocket APIs before production.
Production rules
- Authenticate before selecting the room object.
- Include tenant ID in the object key for multi-tenant apps.
- Rate-limit inbound messages.
- Validate message schema and size.
- Persist important events before broadcasting if clients must be able to replay.
- Use heartbeats/presence timeouts carefully; clients vanish without clean close events.
- Design for reconnect and resume.
Realtime media rules
- Use WebRTC/SFU patterns for audio/video.
- Treat packet loss and jitter differently from data delivery; stale media frames should usually be dropped, not retried.
- Keep application state/signaling separate from media transport.
- Store recordings or generated media in R2; store metadata in D1.
Anti-patterns
- A single global room object for all tenants.
- Trusting client-supplied room IDs without authz.
- Broadcast before validation.
- Using KV to track live presence.
- Assuming every connected socket will close cleanly.