Skip to main content

Overview

meridian-edge is a Cloudflare Workers runtime for Meridian. It compiles the server to WASM and uses Durable Objects for per-namespace state — one DO instance per namespace, co-located with your users at the edge. The TypeScript SDK connects to it identically to the native server — same WebSocket protocol, same REST API, same token format.

Prerequisites

  • Wrangler CLI — npm install -g wrangler
  • Rust with wasm32-unknown-unknown target — rustup target add wasm32-unknown-unknown
  • worker-build — cargo install worker-build
  • A Cloudflare account (free tier works)

Local development

Generate a signing key:
Generate a token for local testing (uses the same gen_token binary as the native server):

Connect with the SDK

No SDK changes needed — the edge worker speaks the exact same protocol as the native server.

Production deploy

1. Set your signing key as a secret:
2. Deploy:
Your worker is live at https://meridian-edge.<your-subdomain>.workers.dev. 3. Issue tokens from your backend:
See Tokens for the full V2 field reference.

Architecture

Each namespace maps to one Durable Object instance:
When a client connects:
  1. Worker validates the token (ed25519 signature, namespace check)
  2. Worker looks up the DO for the namespace via env.NS_OBJECT.idFromName(namespace)
  3. WebSocket is upgraded and forwarded to the DO
  4. The DO manages all connected WebSockets and broadcasts deltas on every op

Webhooks

Register a URL to be called on every op applied to a namespace. Useful for triggering backend pipelines, notifications, or audit systems without maintaining a persistent WebSocket.
Each op fires a POST to the registered URL with this payload:
The X-Meridian-Secret header is included if a secret was registered. Use it to verify the request origin.
Webhook delivery is best-effort — failed requests are not retried. For guaranteed delivery, use the WAL endpoint to replay missed ops.

WAL & point-in-time recovery

Every op written to a Durable Object is persisted to a write-ahead log before being applied to the CRDT snapshot. This means you can replay ops from any sequence number:
Response:
WAL entries older than 7 days are automatically compacted via DO Alarms — no manual maintenance required. Namespaces inactive for 30 days are automatically deleted.

wrangler.toml reference

Limitations

  • Single DO instance per namespace — no cross-region replication at the application level. Cloudflare handles availability automatically; for strict data residency use DO jurisdictions.
  • No Prometheus endpoint — Workers have no long-running process to scrape. Use Cloudflare Analytics Engine or Workers Logpush for equivalent observability.
  • Query Engine performance — POST /v1/namespaces/:ns/query is fully supported but scans all crdt:* keys in DO KV on every request. For namespaces with thousands of CRDTs, prefer the native server which can use indexed storage backends.
  • Live query overhead — SubscribeQuery subscriptions are persisted to DO KV (one write per subscription). Each op re-evaluates all matching live queries by scanning DO KV. This is acceptable for typical namespaces; for very high-frequency ops with many live subscribers, the native server’s in-memory registry is more efficient.