Priostack · Engineering Blog · 21 August 2026 · 16 min read

The Beam and the Dark Space:
QDB, a Database That Owns No Data

Deep dive Data architecture Engineering

Every database you have used answers the same question first: where do I put this? Rows in tables, documents in collections, nodes and edges, vectors in an index. The storage model comes first and the query model is built on top of it, which is why moving between them is a migration rather than a decision.

QDB starts somewhere else. It answers what should I be looking at right now? and it owns nothing at all. No tables, no transactions, no durable indexes. Everything durable lives in the geometric memory underneath. QDB is a lens over it.

That sounds like a technicality. It is the whole design, and this article is about what falls out of it: why the relational, graph and vector models stop being three products, why "forget this" is a different operation from "evict this", and why a query can simulate instead of merely traverse.

1. The beam and the dark space

The metaphor is load-bearing, so it is worth stating precisely rather than decoratively.

geometric memory = dark space ───────────────────────────────────────────────────── billions of positions across thousands of regions, every tenant's data, all of time, durably persisted. ▲ │ resolves handles on demand │ QDB = beam ───────────────────────────────────────────────────── a tenant-scoped, budget-bounded pool of handles that illuminates whatever the current focus points at. lossy at the beam. never at the substrate.

A tenant with 30 GB in the substrate and a 15 MB beam budget never sees 30 GB at once. The beam holds a few hundred thousand handles - symbolic links into the dark space, tens of bytes each. Re-aiming the focus re-resolves the handle set. Dimming the beam destroys nothing.

The closest relatives are not ArangoDB or Neo4j. They are memory-mapped working sets, GPU texture streaming, CDN edge caches and, most of all, attention in a transformer: a large immutable substrate plus a small moving window of what currently matters. What makes it a database rather than a cache is that the window is declared by a query and the substrate is the system of record.

Why bound the working set at all? Because unbounded is a lie that surfaces late. Every store that promises to hold everything in memory eventually meets a tenant who has more than the memory, and the failure is a page fault storm or an OOM at the worst possible moment. Making the budget explicit means the degradation is designed: past the budget the beam dims in a defined order, queries still answer, and the substrate is untouched. A system with a stated ceiling behaves better at the ceiling than one that pretends not to have one.

2. Districts: urbanising the embedding space

The substrate is not one enormous vector space. It is divided into districts: fixed-width regions, each specialised on a single semantic axis, each with its own embedding, its own metric and its own update cadence. Name is a district. Region is a district. Behaviour, finance and transaction shape are districts.

The obvious objection is that a fixed, modest dimension per district is a limitation next to a single very wide space. It is the opposite, and the reasoning is the most interesting design argument in the system.

A single wide embedding collapses every concept into one geometry with one metric and one training regime. Retraining it perturbs everything at once: improve how the space understands regions and you have also, silently, changed how it understands behaviour. Capacity grows by widening the vector, which is the expensive dimension to grow, and the space becomes progressively harder to reason about as more meanings are folded into the same axes.

Districts grow the other way. Capacity grows by adding a district, not by widening one. Each district can be retrained without perturbing its neighbours - refresh the behaviour district and the region district is untouched. Each can use the metric its content actually deserves. We call it embedding urbanisation: a city gains capacity by adding quartiers, each with its own character, not by widening one street until it is a runway.

The trade you are making Composition is not free. A single space gives you cross-concept similarity for nothing: "find me things like this" spans every dimension at once. Districts make you say which axis you mean, or compose a weighted blend explicitly. In exchange you get a space you can evolve one piece at a time. For a system meant to run for years against a changing business, being able to change part of the model without re-validating all of it is worth more than free cross-concept similarity.

3. Exact lookup inside a similarity space

Here is the part that makes QDB a database rather than a vector index with ambitions.

Not every district is semantic. A district may be declared trivial, meaning its embedding is a deterministic projection - a hash, or a one-hot over a small enumeration like {active, suspended, closed}. Identical values land at identical positions. Exactly identical.

In a trivial district, a nearest-neighbour query with a radius of zero and a limit of one is an exact-match lookup. The same primitive that answers "customers similar to this one" answers "the customer whose status is exactly suspended", with the same operation and the same cost model.

semantic district NEAR(behaviour, q, k=10) → the ten most similar trivial district NEAR(status, q, k=1, ε=0) → exact match, or nothing one primitive. the district declares which meaning applies.

This is why relational rows live inside QDB rather than beside it. A system that stores structured records in Postgres and embeddings in a vector store has two consistency models, two backup stories, two failure modes and a synchronisation job between them that is nobody's favourite piece of code. Here "exact" and "similar" are the same query against the same substrate, and the difference is a property of the district, declared once.

4. Entities assembled across districts

An entity - a customer, a device, a reservation - is not a row. It is an assembly of positions across the districts its class participates in, bound together by an identity position that is a structured superposition of them.

The binding is not a foreign key or a join table. It is algebraic: the identity position is composed from the per-district positions in a way that can be inverted, so resolving any one of an entity's addresses reveals the others. Composition and decomposition are operations on positions, not lookups in an index that has to be kept in step.

A class declares which districts it participates in. A customer might live in identity, name, region, behaviour and finance; a device in identity, fleet and telemetry shape. Adding a district to a class extends what can be asked about it without touching the classes that do not participate - the schema-migration problem, reframed as an addressing problem.

5. Edges that can be traversed or fired

QDB has typed edges: OWNS, REFERENCES, TRANSFERRED_TO, between declared entity classes, carrying per-edge attributes like an amount, a timestamp, a confidence.

So far, a graph database. The difference is that an edge type also declares its execution semantics - what kind of arc it is in a Petri net, and with what weight - which gives every edge in the store two entirely different readings.

ModeWhat it doesFamiliar as
Declarative
(the default)
Walks adjacency in the beam, folds attributes, sums and counts. Execution semantics are ignored. Cypher, AQL, Gremlin
Behavioural
(opt in, explicitly)
Materialises the matched subgraph as a Petri net using each edge's declared arc type and weight, runs it, returns the resulting state. Nothing, really

The same declared schema drives both. MATCH a subgraph of accounts and transfers and you can ask two different questions of it: what is the total transferred (declarative), or what happens if these transfers all execute given the balances and the ordering constraints (behavioural). The second is a simulation, expressed as a query, over data you did not have to copy anywhere.

Why opting in matters Behavioural mode is deliberately not the default and deliberately not automatic. A traversal that silently becomes a simulation is a performance cliff and a correctness surprise. Making it an explicit verb keeps the cost model honest: a declarative walk is a walk, and if you asked for a simulation, you know you asked.

6. Focus: the query decides what stays resident

Focus is what the beam is aimed at, and it is the mechanism that replaces the cache-eviction policy you would otherwise be tuning. Rather than a global LRU guessing at relevance, relevance is declared:

FocusIlluminates
SpatialA centre and a radius in one district
TemporalA recency window
TrajectoryEverything on an active execution path
RelationalA seed entity and N hops along an edge type
SemanticA query position in one district
CompositeA weighted blend of the above

Focus assigns every resident handle a score, and when the beam exceeds its budget the lowest scores go first. The consequence is that a fraud investigator working a case and a batch job scoring a month of history get completely different residency behaviour from the same store, without either of them configuring a cache - because each declared what mattered, and eviction followed.

7. Eviction is not deletion

This distinction is small to state and is the one operational property most worth internalising.

Eviction drops a handle from the beam. The positions remain in the substrate; a future focus re-resolves them. It is lossy at the beam and lossless underneath. It happens constantly, automatically, and is never an event anyone needs to be told about.

Forgetting removes a position from the substrate. It is explicit, it is a different verb, and it is the only operation that destroys anything.

Conflating the two is how systems end up with data they cannot delete and caches they cannot trust. Keeping them separate makes a regulatory erasure request a real operation with a real guarantee, rather than an eviction that quietly comes back the next time something re-resolves it. If you have ever tried to prove that a deletion actually deleted something in a system with layered caches, you already know why this is worth a dedicated verb.

8. Snapshots, diffs and lineage

A snapshot is a frozen, named handle table - the beam at an instant. It is kilobytes, because it is a table of symbolic links rather than a copy of anything.

That cheapness is what makes time queries practical. Two snapshots taken a month apart support a diff: what entered this region of the space, what left, what moved and how far. Follow one entity's positions across snapshots and you have its lineage - not an audit log reconstructed from events, but the actual trail of where it has been.

Because positions are derived from state, "how far did this move" is a measurement rather than a metaphor. A customer whose behaviour position has travelled a long way in a month has changed behaviour by a quantity you can put a number on and sort by, without anyone writing a rule about what constitutes a meaningful change.

9. What this is not

Four honest limits, because an architecture article without them is a brochure.

Conclusion

The idea underneath QDB is that a working set is a first-class concept rather than an implementation detail of a cache. Once you commit to that, several things that are normally separate products collapse into one:

None of this is on the public API surface today - it runs inside the product. Read it as the architecture and the reasoning behind it. The geometric memory article covers what the positions themselves mean and how execution trajectories are compared, and BQL covers the query language that sits on top of this one.

Talking to us about it If you are evaluating this shape of system for a regulated workload - in particular the eviction-versus-erasure distinction, or the single-substrate argument - write to support@priostack.com. The agentic credit tutorial is the fastest way to see the public API these ideas sit beneath.

Priostack Engineering

Technical deep-dives on process automation, workflow engines, and the systems behind Priostack.