The term engine design is done. “VIP customer” has a definition. “Net revenue” has a formula.

Then I got stuck.

A user types “Show me last month’s VIP customer revenue.” What’s supposed to happen inside the system?

First, Decide Where the Answer Comes From

There are multiple sources that can produce an answer. You can traverse the graph. You can write SQL to pull from the DW, or just run a vector search against past queries.

The answer changes depending on where you send it.

Send “VIP customer revenue” to SQL and Vanna assembles tables to produce a number. Send it to the graph and it pulls term definitions and relationships first. You might think: just send it to all three and merge. Try it… they conflict immediately.

Same word “churn rate,” but the marketing report number and the CRM dashboard number don’t match. A human reads the context and picks the right one. An agent just sees two different numbers.

When a Question Comes In, Who Moves First?

When a question comes in, the Router catches it first. It reads term_type from the term metadata – metric goes to SQL, concept goes to the graph. If it routes wrong here, everything downstream falls apart. Every term already has a type and linked columns nailed down. So the Router just reads and branches. Done.

…what happens without this? You end up asking the model “Is this SQL or graph?” every time. Try it a few times and you’ll feel it immediately. It doesn’t hold up.

The real headache is the Supervisor.

When answers come back from multiple sources with different numbers, someone has to decide whose answer wins. If you don’t force a single standard, it turns into a fight every time. Marketing says “churn rate 12%.” CRM says “churn rate 8%.” Different formulas, neither wrong.

So I just forced a priority order. Called it HoT – Hierarchy of Truth. The term engine’s standard definition wins, SQL execution results come next, vector search ranks last. Without this, the Supervisor has to ask the model “which one’s right?” every time there’s a conflict.

The Graph DBA validates the schema before any Cypher query fires – if someone writes a query with an unregistered term, it gets blocked before execution.

What I Still Don’t Know

The thing I’m most uneasy about is compound questions.

“Analyze VIP customer purchase patterns over the last 3 months” – that needs both the graph and SQL. The Router reading term_type and routing should handle most single questions fine, but when something like this comes in, it needs to be split. Where to cut, what order to send. I’ve sketched it out in the design, but I won’t really know until I run it.

HoT is also on my mind. What if the definition is six months old? I’ve added staleness detection, but that’s a problem for later.

The Graph DBA is the opposite worry – blocking too aggressively.

Next: Running It Against a Real DB

After finishing the sub-module design, I’m running an A/B experiment on the sql-tutorial DB with 21 tables. EX (Execution Accuracy) +15%p needs to land. If it doesn’t, the design gets torn up. Push this on intuition and it’ll blow up later.

If the numbers come in, I’ll write about it.


Documenting the process of designing and building DataNexus. GitHub | LinkedIn