Don't put an LLM in charge of your production database A developer recounts how a GenAI assistant caused a $4,200 query failure and downtime on a production database, arguing that Text-to-SQL agents need hard infrastructure constraints rather than blind trust. The post compares three architectural patterns—Raw Agent, Semantic Layer, and Frozen Schema—and emphasizes the importance of semantic layers and strict governance to prevent costly errors. Last June, a junior analyst pushed a "helpful" GenAI assistant to our internal Tableau-connected lakehouse. Within forty minutes, the agent generated a SELECT across a 40-terabyte partitioned table joined against a cross-region S3 bucket. The query didn't just fail; it locked the Databricks SQL Warehouse, blew our monthly compute budget in a single afternoon, and triggered a PagerDuty incident that ruined my kid’s birthday dinner. That query cost us $4,200 in DBU burn and an hour of downtime for our actual business stakeholders. Why I chose this topic:I’m tired of seeing engineers treat Text-to-SQL as a magic wand rather than a dangerous, non-deterministic interface. I wrote this because production-grade data governance requires moving past "prompt engineering" into hard, infrastructure-level constraints. The decision you are facing isn't whether to use LLMs for data—it's whether you want to build an expensive, unreliable hallucination engine or a system that actually respects your data perimeter. You are currently choosing between three architectural patterns: the "Raw Agent" blind trust , the "Semantic Layer" the guardrail approach , and the "Frozen Schema" the brute-force approach . The "Raw Agent" is what happens when you just point a LangChain SQLDatabaseChain at your Unity Catalog metastore. It’s the "move fast and break things" approach, except you're breaking your company's P&L. The "Semantic Layer" uses an intermediate abstraction—think dbt Semantic Layer or a specialized metric store—that acts as a firewall between the LLM and the raw SQL. The LLM talks to the model, not the table. The "Frozen Schema" is the nuclear option. You don't give the LLM the entire catalog. You give it a strictly curated, subsetted DDL definition of exactly three tables, with no write permissions, and a LIMIT clause hard-coded into the underlying execution proxy. Photo by Zulfugar Karimov on Unsplash In production, latency is a feature, not a bug. If your Text-to-SQL agent takes 15 seconds to parse, plan, and execute, your business users will go back to asking the data team for CSVs. The Raw Agent is a nightmare here. If you provide a schema with 500 tables, the token count for the system prompt alone will set you back significant latency on every single request. Using gpt-4o , you’re looking at 2-3 seconds of TTFT Time To First Token just to generate a JOIN that will likely fail because it missed a join key on a non-indexed column. The Semantic Layer wins on efficiency. By exposing only core metrics— revenue by region , churn rate monthly —the LLM has a search space of 20 variables instead of 20,000 columns. You can cache these responses in Redis for common queries. With a 300ms retrieval time from cache, you’re looking at a sub-second user experience that feels like a real product. The biggest failure mode in Text-to-SQL is the "Syntactically Correct, Semantically Wrong" query. The LLM might write a perfect JOIN statement that executes without error, but calculates gross margin by subtracting shipping costs from revenue when your actual business logic requires revenue - cost of goods sold - shipping costs . Raw Agents fail silently. They give the user the wrong number, and the user makes a million-dollar decision based on it. There is no error message because the SQL is valid. The Semantic Layer forces the LLM to use pre-defined logic. You move the source of truth from the LLM’s "knowledge" into your dbt project. When the LLM asks for "margin," it hits a view that already contains the logic. If the LLM tries to add a column that doesn't exist, the query parser throws an AnalysisException before the data is even touched. Photo by Logan Voss on Unsplash Governance is where most of these projects die. If you aren't using Row-Level Security RLS and Column-Level Security CLS , you are one prompt away from a data breach. With the Raw Agent, you have to implement RLS on the warehouse side, but you’re still exposing your entire schema. You need to keep your INFORMATION SCHEMA restricted. If you use Databricks, you’re looking at complex GRANT hierarchies. It’s brittle. If you add a new column for PII, you have to remember to hide it from the LLM’s system prompt, or you're leaking sensitive data. The Semantic Layer shifts the burden to the platform team. You maintain the semantic layer, and the agent acts as a client of that layer. This is the only way to scale. You don't grant the LLM a connection to the raw tables; you grant it a service account connection to the semantic interface. The service account has SELECT access only to the views you've blessed. I’d pick the Semantic Layer every single time. If you’re building in a regulated industry—healthcare or finance—you don't have a choice. Here is my non-negotiable stack: LIMIT enforcement on every query. If the LLM doesn't include LIMIT 100 , the FastAPI layer injects it automatically before sending it to the warehouse. patients table, the agent can't generate a query that hits it.The caveat? It’s harder to build. You have to write the code that maps natural language intent to specific semantic metrics. It’s not "plug and play." But in production, "plug and play" just means "plug in and pray." Don't let an LLM write raw SQL against your production lakehouse. Build a layer, wrap it in strict permissions, and force the agent to play by your rules. Your PagerDuty rotation will thank you.