Your internal data is worth more than the AI you put on top of it
The model was always going to be fine. The thing that decides whether anyone trusts the answer is the data layer underneath it — and that's the part nobody budgets for.
A CTO watches a fifteen-minute demo, sees a chatbot answer a question about the business in plain English, and signs off on an AI initiative that afternoon. Six weeks later the thing is technically working and nobody trusts it. The model is fine. The model was always going to be fine. What nobody looked at was the warehouse it was pointed at — a few hundred tables, half of them undocumented, where the word active means five different things depending on which analyst built which report.
This is the pattern we see most often, and it is the inverse of the one most companies budget for. The money goes to the model; the data layer is inherited as-is. It should be the other way around. The model is the cheap, rented, interchangeable part. Your internal data — specifically, whether it means one clear thing — is the part that decides whether any of it works.
The part everyone thinks is hard is now the cheap part
Turning a question in English into a SQL query used to be a real problem. It is not anymore. Any current frontier model writes competent SQL against a schema it can see, and the gap between the best model and the second-best at this task is not something your users will ever notice. Text-to-SQL is commoditized. It was never going to be your advantage, and building as if it is your advantage is the first wrong turn.
Take the generation as a solved input. What’s left is the only question that actually matters: does the number that comes back mean what the person asking thinks it means? That question has nothing to do with the model. It’s answered entirely by the layer underneath.
The five definitions of “active”
Ask a system “how many active players did we have last month” and watch what happens. In a typical iGaming schema, active could mean logged in, placed a bet, staked real money, deposited, or simply “not self-excluded.” Each is a defensible definition. Each lives in some report somewhere. The model, handed this schema, will pick one — confidently, and with a perfectly good query. It isn’t wrong. It just answered a question the data never decided the answer to.
Now scale that across every term a business runs on. In this domain: GGR versus NGR, first-time deposit, average revenue per user, lifetime value. Every one is a landmine if the schema doesn’t resolve it to exactly one thing. The failure isn’t a hallucination — that’s the failure people prepare for. It’s worse, because it’s plausible: a real query, a real number, quietly computed against the wrong definition, trusted precisely because it looks correct. You can’t prompt your way out of this. “Be careful about how you define active” is not a fix; it’s a wish.
What the data layer actually is
“Fix your data” usually gets heard as “clean the data” — dedup, backfill nulls, fix encodings. That’s hygiene, and it’s not the point. The data layer that earns its keep does three specific things, none of which a model can do for you:
- One canonical definition per term, written where the query engine can read it. Not in a wiki, not in an analyst’s head — attached to the object being queried. There is one
active_players, it means one thing, and that meaning travels with the schema. - Boundaries enforced in the data, not the application. Row-level isolation — which customer, which tenant, which hierarchy a caller may see — lives in the views, so a query with no
WHEREclause still returns only what the caller is allowed to see. If isolation lives in application code, a clever query routes around it. If it lives in the data plane, it can’t. - Self-description. The schema explains itself. Column comments carry business meaning, and the model reads them the same way a new analyst would — which means the model can’t drift from definitions the schema doesn’t hold.
Concretely, the term carries its own definition — pinned to the object every query hits, not left to whoever builds the next dashboard:
api.active_players — one definition, used everywhere
means staked real money in the trailing calendar month
not logged in · deposited · merely registered
scope caller's hierarchy only, enforced in the view
The model doesn’t need to be told what active means. It reads it. And more importantly, so does the next engineer, and so does the auditor.
The gateway is thin on purpose
Our own SQL gateway — the read-only service that sits between the AI and the database — is deliberately dumb. It verifies a token, scopes the session to the caller’s slice of the data, runs the query read-only under a timeout, returns rows. That’s it. It doesn’t parse the SQL for safety. It doesn’t understand the business. All the value — isolation, meaning, the guarantee that an answer is both safe and correct — lives one layer down, in the views.
Call it 80/20. The curated data plane is roughly 80% of the real work; the model call is the easy 20%. That ratio is not an accident of our stack — it’s the whole thesis. It’s also the right place to put your investment, because the two layers age at completely different rates. The model you use will be replaced within a year, probably twice, and each swap should be a config change. The semantic layer — what your numbers mean, who can see them — is still true in 2028. Spend on the part that compounds.
What to do first, and what to never do
If you’re standing at the start of one of these projects, the order is: a definition pass (get the business to agree, once, what each term means), then a semantic layer that encodes those definitions where queries run, then an access-pattern audit (who asks what, and what may they see). Then wire up a model. Done in that order, the model integration is almost boring — which is the goal.
What to never do: treat the model’s instructions as a substitute for a schema that can’t lie. Every guardrail you write in a prompt is a guardrail you’re trusting a probabilistic system to honor under paraphrase. Every guarantee you move into the data plane is one the database enforces whether the model cooperates or not.
The example here is iGaming, but swap the nouns and nothing changes. In payments it’s settled versus authorized versus captured. In lending it’s delinquent as of when. In logistics it’s delivered by whose timestamp. The vertical decides the vocabulary; the pattern is identical everywhere transactional data meets a question asked in English.
The uncomfortable version of all this: if your data layer is good enough, your choice of AI barely matters, because everyone is renting the same handful of models anyway. The teams that get real leverage over the next few years won’t be the ones with the best model. They’ll be the ones whose internal data has an opinion.
Written by the team at datalabz. We’re an applied engineering studio that builds AI-augmented systems for transactional and data-heavy businesses — the SQL gateway described above is one of our own. If this is the kind of work you think about, get in touch.