Docket Docs
Developer GuideArchitecture

Control Plane vs Data Plane

How Docket separates operational control from data processing.

Control Plane & Data Plane

Docket separates operational concerns (control plane) from data processing (data plane). This keeps RBAC, observability, plugin onboarding, and configuration management clean and independently scalable.

Why separate?

ConcernControl PlaneData Plane
RBACManage policies, principals, access rulesEnforce policies on every query/ingest
ObservabilityAggregate metrics, health, audit logsEmit per-request spans and events
PluginsRegister, validate, onboard adaptersUse adapters without knowing their provenance
ConfigHot-reload YAML, env var resolutionRead resolved config snapshots
ScaleSingleton (one per cluster)Horizontally scalable (many instances)
SecurityInternal/admin network onlyExposed to users and external UIs

Architecture

┌─────────────────┐         ┌─────────────────┐
│   Control Plane │◄───────►│   Data Plane    │
│   (Port 3001)   │  shared │   (Port 3000)   │
│                 │  store  │                 │
│  /admin/config  │   &     │  /ingest        │
│  /admin/plugins │  queue  │  /query         │
│  /admin/rbac    │         │  /memories      │
│  /admin/health  │         │  /health        │
└─────────────────┘         └─────────────────┘
         │                           │
         └───────────┬───────────────┘

            ┌─────────────────┐
            │  Shared Core    │
            │  (interfaces,   │
            │   models,       │
            │   config)       │
            └─────────────────┘

Shared resources

Both planes share:

  • Store (SQLite/Postgres) — control plane writes config/RBAC tables; data plane reads them
  • Queue — control plane schedules plugin jobs; data plane processes ingestion and decay jobs
  • Config loader — control plane resolves and validates; data plane consumes the snapshot

Running locally

Standalone (both planes in one process)

npm start

This starts a unified server where control routes are mounted under /admin/.

Separate processes

# Terminal 1 — control plane
npm run start:control
 
# Terminal 2 — data plane
npm run start:data

API boundary

Control Plane routes (/admin/*)

MethodRoutePurpose
GET/admin/healthAggregated adapter health
GET/admin/configResolved runtime config
POST/admin/configHot-reload config (validates first)
GET/admin/pluginsList registered adapters
POST/admin/pluginsRegister/onboard a new adapter
DELETE/admin/plugins/:nameDeregister an adapter
GET/admin/rbac/policiesList RBAC policies
POST/admin/rbac/policiesCreate or update a policy
GET/admin/metricsPrometheus-compatible metrics

Data Plane routes (/*)

MethodRoutePurpose
GET/healthData plane health only
POST/ingestIngest a file or text
POST/queryNatural language query
GET/memories/:idGet a memory
POST/memoriesCreate a memory directly
PATCH/memories/:idUpdate a memory
DELETE/memories/:idDelete a memory
GET/memories/:id/relationsGet memory graph

Adapter registry separation

  • Control plane owns the AdapterRegistry — it loads, validates, and caches adapters.
  • Data plane receives a read-only snapshot of the registry at startup. It cannot load new adapters dynamically; it must be restarted or signaled to refresh.

This prevents a compromised data plane from injecting malicious adapters.

Deployment modes

ModeUse caseHow
UnifiedLocal dev, small deploymentsSingle process, /admin prefix
Split processProduction self-hostedTwo Node processes, shared SQLite
Split networkEnterprise / multi-tenantControl plane on internal VPC; data plane on public subnet
ServerlessEdge / lambdaData plane as serverless handler; control plane as separate admin function

On this page