How NodeDB Handles Multi-Model Differently
Source: Dev.to
Introduction
In the previous article I explained where NodeDB stands in the current multi‑model landscape.
This post tackles the next question: how does it actually work?
Short answer: one engine cannot do everything.
NodeDB splits the problem into core engine families, then builds specialized models on top of the right base—while keeping everything inside a single database boundary.
Core idea
- Some models get their own real engine.
- Some models grow from another strong native engine.
- The planner knows the difference.
- The user does not have to split the stack into multiple databases just because the workload widens.
Start from the core, not from the label
When people say “multi‑model database” the phrase usually hides one of several shortcuts. It can mean:
- One strong database with extensions.
- One document system with a broader marketing surface.
- Several services under one product name.
- One generalized storage shape stretched across too many models.
That is not the route I wanted.
The starting question for NodeDB was simpler—and harder—at the same time:
What are the real engine families needed if this database is supposed to handle broad workloads without turning every new requirement into more stitching?
Current engine families
- Document
- Strict
- Graph
- Vector
- Columnar
- Key‑Value
- Full‑Text Search
There are also models that should be native but do not need a fully separate engine family if they already have the right base:
- Time‑Series (on Columnar)
- Spatial (on Columnar)
That split matters because it avoids two bad extremes:
- Pretending every model is the same under the hood.
- Creating a separate mini‑database for every capability.
The core engine families
The concrete part is what these engines actually are.
Document– the flexible‑record engine. In NodeDB this means schemaless records, MessagePack storage, and CRDT‑oriented sync paths for local‑first use cases.Strict– the structured‑record engine. It is closer to row‑oriented access, uses a different storage shape, and is meant for workloads that care about predictable fields and faster direct access—not just schema validation on top of documents.Graph– not “document plus links”. It has its own adjacency structures, traversal paths, and graph‑native operations.Vector– not “just add embeddings somewhere”. It has its own ANN path, quantization pipeline, and distance behavior.Columnar– the analytical base: compression, scan‑heavy reads, predicate push‑down, and the layout you want when the workload is closer to analytics than OLTP.Key‑Value– exists for direct‑lookup workloads that should be simple and cheap instead of being routed through a heavier model.Full‑Text Search– has its own ranking and tokenization behavior (BM25, stemming, stop‑word handling, fuzzy matching, hybrid retrieval). These capabilities should not be faked with normal filtering.
These are the parts many multi‑model products blur. The names are easy; the backing engine choices are the hard part.
Why Strict matters so much
Strict is especially important because this is where a lot of multi‑model systems get vague. From the outside, Strict can look like “document plus schema rules”. That is not enough.
In NodeDB, Strict exists because structured workloads need a different path:
- Fixed‑field expectations.
- Different storage behavior.
- Different access patterns.
- Different planner assumptions.
- Different performance goals.
In the current repository direction, Strict is treated as a row‑like storage mode with direct field access—not just a document collection that rejects invalid writes.
That distinction matters: if a multi‑model database cannot give structured data a serious path of its own, the “multi‑model” story is already weak for a large class of real applications.
Specialized models should grow from the right foundation
This is where Time‑Series and Spatial fit.
I do not think every model deserves its own isolated engine family just for the sake of appearances. Sometimes the right design is to start from a strong native base and specialize from there. In NodeDB that base is Columnar.
Time‑Series (on Columnar)
- Columnar layout fits scan‑heavy reads.
- Compression matters.
- Aggregation matters.
- Retention and roll‑ups matter more than point‑update behavior.
The current repo reflects this: Time‑Series is described as a columnar profile with ILP ingest, continuous aggregation, PromQL support, and time‑oriented SQL functions.
Spatial (on Columnar)
- Belongs near Columnar because analytical and geospatial workloads often overlap.
- Adds native behavior: spatial indexes, geohash/H3‑style locality tools, and geometry predicates.
Pattern:
- Separate engine families where the workload is genuinely different.
- Specialized native profiles where another engine already provides the right foundation.
How NodeDB keeps coherence
Collecting engines under one brand does not solve multi‑model; it merely moves the boxes closer together. The harder problem is coherence:
- How does a mixed workload stay in one system?
- How does the planner choose the right path for each model?
- How do you avoid weakening every model just to make the interface look uniform?
For NodeDB, the answer is not a single generic query path for everything—that would flatten the models.
Instead, we use dedicated query and planner treatment where model semantics really differ, while still keeping them within one database boundary.
Strictis planned with stronger assumptions, not like schemaless documents.Vector,Graph,Full‑Text Search, and other specialized models receive their own optimized planning paths.
By giving each engine family the treatment it deserves, NodeDB maintains performance and feature richness without sacrificing the simplicity of a single, coherent database system.
Coherence in a Multi‑Model Database
When we talk about coherence we mean more than just “one query language” or “one product.”
It implies:
- One database boundary – a single logical system that users interact with.
- Shared system‑level coordination – common metadata, security, and transaction handling.
- Model‑specific execution paths where needed – each model (graph, vector, time‑series, etc.) gets its own optimized engine.
- Fewer cross‑system hops when workloads mix different models.
Why This Is Different From “Pseudo” Multi‑Model
The distinction I care about most is how “pseudo” multi‑model solutions usually fail in one of two ways:
- Everything is pushed through one generic core – the models exist but feel weak.
- Every serious model becomes another extension, service, or external database – the models stay strong, but the user must absorb the integration cost.
NodeDB aims to stay between those two failures. That’s why the design is split the way it is:
- Real engine families where the workload needs real specialization.
- Native profiles where a strong base already exists.
- Planner‑level respect for the differences between models.
- One database boundary for mixed workloads.
What This Means in Practice
If NodeDB works the way I want it to, the practical result should differ in a few concrete ways:
- Graph queries follow graph‑native structures and algorithms instead of pretending edges are just another document field.
- Vector search uses a real ANN (Approximate Nearest Neighbor) path with its own indexing and quantization choices, not a thin side feature.
- Strict collections behave like a serious structured model with stronger planner assumptions and faster direct‑field access.
- Time‑series inherit the strengths of columnar execution instead of being simulated on top of an unsuitable engine.
- Spatial gets native spatial behavior without forcing the user into another database.
- A workload that mixes records, vectors, search, and graph stays inside one system instead of turning into a chain of remote calls.
These tests are more meaningful than simply asking whether the product can list many model names.
The Risk
This approach is harder for obvious reasons:
- It is easier to start with fewer engines.
- It is easier to flatten more behavior into one generic layer.
- It is easier to delay the planner work.
- It is easier to turn more models into later add‑ons.
The risk is whether NodeDB can keep this depth and coherence once real workloads start pushing every corner of the design.
Why I Still Prefer This Route
Even with that risk, I still think this is the more honest way to build a true multi‑model database.
The point is not only to support many models.
The point is to support them with the right engine shape, the right planner behavior, and the right database boundary.
If that holds up, then NodeDB becomes interesting for a real reason, not just because it can claim a long feature list.
If you want to follow how NodeDB works at the engine level—where this design holds up and where it still needs to prove itself—follow the NodeDB blog. I will keep sharing the architecture, trade‑offs, and deeper implementation decisions as the database evolves.