Architecture Overview
NodeDB splits work across three planes connected by lock-free ring buffers. Each plane does exactly what it is best at and nothing else. Mixing planes is a correctness bug.
┌───────────────────────────────────────────┐
│ Control Plane (Tokio) │
│ SQL parsing, query planning, connections │
│ Send + Sync, async │
└─────────────┬──────────────┬──────────────┘
│ SPSC Bridge │ Event subscriptions
│ │
┌─────────────▼──────────┐ ┌▼────────────────────────────────────┐
│ Data Plane (TPC) │ │ Event Plane (Tokio) │
│ Physical execution ├─►│ AFTER trigger dispatch │
│ Storage I/O, SIMD │ │ CDC change streams │
│ !Send, io_uring │ │ Cron scheduler │
│ Emits WriteEvents │ │ Durable pub/sub, webhook delivery │
└────────────────────────┘ └─────────────────────────────────────┘
Plane Boundaries
| Plane | Does | Does not do |
| Control Plane | SQL parsing, query planning, connection handling | Event processing, trigger execution, storage I/O |
| Data Plane | Physical I/O, SIMD math, WAL append, BEFORE triggers | Event delivery, AFTER triggers, cross-shard work |
| Event Plane | AFTER triggers, CDC, cron, webhooks, durable pub/sub | Query planning, storage I/O, TPC tasks |
If code needs to cross a plane boundary, it goes through the SPSC bridge (Control-Data) or the Event Bus (Data-Event).
Query Entry Paths
SQL path — All user-facing interfaces accept SQL. The Control Plane parses via sqlparser, plans via EngineRules, and dispatches a SqlPlan through the SPSC bridge to the Data Plane.
psql / ndb CLI / HTTP /query
→ SQL parser (sqlparser-rs)
→ EngineRules::plan_*()
→ SqlPlan → SPSC Bridge → Data Plane
Native opcode path — The Rust SDK and FFI/WASM bindings dispatch typed opcode messages over the NDB protocol. The Control Plane converts them directly to a plan, skipping SQL parsing.
nodedb-client / FFI / WASM
→ Native opcode + typed fields
→ build_plan()
→ PhysicalPlan → SPSC Bridge → Data Plane
Both paths produce the same plan and execute identically on the Data Plane.