Skip to content

Graphs & Shards

A graph is a named collection of nodes and edges, scoped to a single tenant.
Each graph has its own schema (node types, edge types) and its own physical storage.

Tenant ── has many ──▶ Graph Projects
Graph Project ── has one ──▶ GraphShard (Durable Object)
GraphShard ── stores ──▶ nodes[], edges[]

Every graph is backed by a Cloudflare Durable Object named {tenantId}:{graphId}.
Inside that Durable Object, an embedded SQLite database stores:

CREATE TABLE nodes (
id TEXT PRIMARY KEY,
type TEXT NOT NULL,
data TEXT NOT NULL, -- JSON blob of node properties
embedding TEXT, -- vector (for agentic queries)
created_at INTEGER,
updated_at INTEGER
);
CREATE TABLE edges (
id TEXT PRIMARY KEY,
type TEXT NOT NULL,
source_id TEXT NOT NULL,
target_id TEXT NOT NULL,
data TEXT NOT NULL,
created_at INTEGER,
FOREIGN KEY(source_id) REFERENCES nodes(id),
FOREIGN KEY(target_id) REFERENCES nodes(id)
);
  • Every (tenantId, graphId) pair maps to a unique Durable Object instance.
  • Durable Objects are physically isolated: data from Tenant A never shares memory or storage with Tenant B.
  • The DO name is computed as idFromName(`${tenantId}:${graphId}`).

Graph metadata — project names, schema definitions, tenant associations — is stored in Cloudflare D1 (PostgreSQL-compatible SQL).
The graph data (nodes, edges) lives inside the Durable Object.

D1 (metadata) Durable Object (data)
──────────────────────────── ──────────────────────────────
graphProjects (id, name, …)
graphs (id, projectId, …) ──▶ GraphShard {tenantId}:{graphId}
nodeTypes (graphId, type, …) nodes table
edgeTypes (graphId, type, …) edges table
  1. POST /graphs — creates a D1 record; the Durable Object is instantiated lazily on first write.
  2. DELETE /graphs/:id — removes D1 metadata; the DO is garbage-collected by Cloudflare after its storage is cleared.
  3. Shards can be backed up to R2 via ops-control on a cron schedule.