Let me say something that might sound odd coming from someone who uses AI tools every day: most of the work I see teams sending to LLMs should not be going there. Not because LLMs are bad at it. Because there's a better tool for it, and the better tool is free, deterministic, and can encode your domain expertise instead of guessing at it.
I'm talking about generators. And the confusion between what a generator does and what an LLM does is quietly costing teams money, consistency, and - most expensively - trust in their own output.
The Bill You're Not Reading Carefully Enough
An LLM API call costs money. Not a lot per call, usually, but software doesn't make one call. It makes thousands, tens of thousands, millions - and those costs compound in a way that looks manageable on the first invoice and alarming on the twelfth.
But the dollar cost is actually the smaller problem. The bigger problem is that every LLM call is a roll of the dice. Not a wild roll - the model is sophisticated, the probability distribution is well-shaped - but still a roll. Ask it to generate a route handler for a new resource today and you get one thing. Ask it tomorrow, with a slightly different phrasing, and you get something slightly different. Ask five developers on your team to prompt it for the same thing and you'll get five variations that are all "correct" in the way that a plausible median is correct, none of which necessarily match how your system does it.
The inconsistency isn't only the model's fault. A large part of it is us.
We prompt differently every time - different context, different level of detail, different day, different mood. We don't give the model our validation conventions, our error-handling patterns, our column naming rules, our transaction requirements. We expect it to infer them from a few lines of description and the general shape of its training data, and then we're surprised when the output needs three rounds of editing before it fits the codebase.
The model is doing its job. We're not doing ours, because "our job" in this context is too expensive and too inconsistent to do well at scale.
What a Generator Actually Does
A generator doesn't guess. It reads your schema - your actual database schema, with your column names, your types, your foreign keys, your constraints - and from that single source of truth it produces, deterministically and repeatably, the artifacts that schema implies: route handlers, SQL queries, form templates, validation schemas, type definitions, translation keys.
Same input. Same output. Every time.
The domain knowledge that an LLM has to re-derive on every call - what this column type means in your application, what this relationship implies about your join patterns, how this kind of form should validate - lives permanently in the generator. You encoded it once. You reviewed it once. You made the decision about how your application handles decimal precision in currency fields, or how it handles soft deletes, or what it does with nullable foreign keys - and that decision lives in the generator forever, applied consistently to every resource it produces.
When you find a bug in the pattern - a missing transaction boundary, a validation edge case you hadn't considered - you fix it in one place, run the generator again, and every resource it has ever produced gets the corrected behavior. With AI-generated code, the same logical mistake exists in twenty files in slightly different forms, each one requiring manual discovery and individual repair.
The economics of this are not close. Deterministic generation is dramatically cheaper and more consistent than probabilistic generation for any task with a stable, codifiable structure. And business software is, in large part, made of exactly that kind of task - and if you want to understand what the failure mode looks like when it isn't treated that way, Quality Doesn't Matter Until It Does goes into it at length.
But LLMs Did the Hard Part
Here is the part people miss when they hear "use a generator instead of an LLM": I'm not suggesting you go back to writing generators by hand from scratch, which is a significant investment. I'm suggesting you use an LLM once - once, carefully, with full context and your actual schema - to help you build the generator that then does the work forever.
This is a completely different use of the tool, and it's the right one. LLMs are expensive per call but extremely good at reasoning through a novel, complex problem with adequate context. Building a generator is exactly that kind of problem: understanding your domain, your patterns, your conventions, your edge cases, and turning that understanding into a codified, auditable, repeatable process. Do it once. Pay for it once. Let the result compound.
The distinction matters more than it might look: using an LLM to generate a route handler on demand is like asking a brilliant consultant to draft every email you send. Using an LLM to build a generator is like asking that consultant to write your communication guidelines so your whole team writes consistently from now on - and never having to call them again for the same thing.
The Inconsistency Problem Has a Human Origin
There's an uncomfortable truth in any honest post-mortem on AI-generated output quality: a lot of the variability we attribute to the model is actually variability we introduced. The same LLM given the same context produces much more consistent output than the same LLM given different context by five different developers over three months.
We don't give it the same context. We don't prompt at the same depth. We don't maintain the same conventions in our instructions. We don't inject the same domain constraints. Some of us give it the full schema. Some of us give it a vague description. Some of us give it examples from the codebase. Some of us don't.
The result is output that looks consistent to someone who hasn't read it carefully, and isn't. This is a genuine engineering problem, not a user-error story - because asking every developer on a team to maintain perfect, identical, comprehensive prompts across every task is not a realistic engineering process. It doesn't scale. It degrades under deadline pressure. It depends on individual discipline in a way that no serious production system should depend on.
A generator removes the human variability from the loop entirely. The conventions aren't in someone's prompt - they're in the generator's logic, where they can be reviewed, versioned, and trusted.
Steering Files Help - Up to a Point
The industry has noticed the inconsistency problem, and the response has been steering files: CLAUDE.md, AGENTS.md, skills definitions, system prompts checked into the repository. The idea is sound - give the model a stable, shared context so every developer on the team is starting from the same place rather than from whatever they happened to type today.
And they do help. A well-written CLAUDE.md that describes your project's conventions, your preferred patterns, your naming rules, your testing approach - that genuinely narrows the variance. The model reads it, and the output is measurably more consistent than it would be without it. I use them. I'd recommend them.
But they are not a catch-all, and mistaking them for one is where teams get into trouble.
Steering files are still instructions to a probabilistic system. The model reads them and does its best to honor them - but "does its best" is not the same as "always does." The instructions can conflict with each other. They can be ambiguous in ways that only surface in specific edge cases. They can drift out of sync with the actual codebase as the project evolves, silently, without anyone noticing, because they're a text file rather than an executable specification. And they don't help at all with the parts of consistency that depend not on convention but on correctness - the transaction boundary that needs to be there, the rounding rule that must match the contract, the validation that has to be exactly right.
There's also a maintenance cost that compounds quietly. A steering file that nobody is actively curating becomes a liability - a set of instructions that partially describe a system that has moved on, pointing the model in directions that are no longer accurate. Keeping it current requires the same kind of discipline that writing good prompts requires, distributed across the whole team, sustained over the life of the project. That is harder than it sounds.
A steering file is a better input to a probabilistic system. A generator is a different system entirely.
The distinction is the kind that matters in production. Use steering files - they help, and the good ones help a lot. But use them for what they're good at: guiding the model on tasks that genuinely require judgment, not for tasks that have a deterministic correct answer your tools should already know.
MCPs Are the Bridge, Not the Replacement
There's a third piece to this, and it's where the architecture comes together in a way that actually makes sense.
Model Context Protocol tools - MCPs - give an LLM direct, structured access to the systems around your application: your database, your file system, your APIs, your documentation. But the most useful thing an MCP can do isn't to let the model generate code directly. It's to let the model call your generator.
This is the shape that works in practice. The developer describes what they need - a new resource, a new form, a new endpoint - and the LLM understands the intent, reasons about the context, and calls the MCP. The MCP hands off to the generator. The generator produces the correct, consistent, deterministic output it always produces, because that's what generators do. The LLM was useful as an interface, as a reasoning layer, as the thing that understood what was being asked. The actual authorship of the code stayed where it belongs - in a process you reviewed, trust, and can audit.
This is the distinction worth holding onto: use the LLM to describe what you need, and let every tool at your disposal help you achieve it in a repeatable and correct way. The model is at its best when it's orchestrating - routing intent to the right tool, composing results, reasoning about what should happen next. It's at its worst when it's freehanding code that has a deterministic correct answer your system already knows how to produce.
The question to ask about any generation task isn't "can the LLM do this?" - it almost certainly can. The question is "does this task have a correct, stable, codifiable answer?" If yes, that answer belongs in a generator, and the LLM's job is to call it.
Consistency Is What Business Actually Buys
I want to be direct about what's really at stake for teams building software that runs businesses, because the appeal of "just use the LLM for everything" is strong and the counter-argument needs to be concrete.
Business software's value is not in novelty. It's in reliability. The application that calculates payroll correctly this Friday, next Friday, and every Friday for the next five years is worth infinitely more than the application that gets it right four Fridays out of five. The inventory system that handles concurrent orders consistently under load is worth more than the one that handles them correctly most of the time.
Consistency is what business actually buys when it buys software. And consistency - the real kind, the kind that survives developer turnover and midnight deployments and the edge case nobody tested - comes from codified, deterministic, auditable processes. Not from a system that produces a good-looking output eighty-five percent of the time and a subtly wrong one the rest.
We're enormous fans of LLMs. What they can do for reasoning, for synthesis, for working through complex and novel problems, is genuinely transformative. But business doesn't run on brilliance that shows up most of the time. It runs on correct, predictable behavior that can be counted on every time.
The Shape of a Sane Approach
It doesn't have to be all or nothing. The approach that has worked best for us is thinking in layers rather than making either/or choices.
The LLM is the interface - it understands intent, reasons about context, decides which tool to reach for. The MCP is the integration layer - it connects the model to the real systems around it, including the generator. The generator is the workhorse - it takes a stable, well-understood task and produces correct output every time, because you encoded the right answer into it once and it has been applying that answer faithfully ever since.
These layers compose. "I need a new resource for customer invoices" goes to the LLM, which understands what that means in the context of your project, calls the MCP, which triggers the generator, which produces the route, the SQL, the form, the validation, and the translation keys - consistently, correctly, for free. The LLM contributed what it's actually good at: understanding a description and routing it to the right tool. The generator contributed what it's actually good at: deterministic, auditable output from a known-good pattern.
Building and improving the generator itself is where you spend a careful, well-contextualized LLM session. Encode your decisions into the generator's logic. Do it once. Pay for it once. Let the result compound.
This Is What Reepolee Is For
Reepolee is a codegen starter built around exactly this philosophy. It introspects your database schema and generates a consistent, full-stack application layer from it - routes, SQL, forms, validation, translations - using patterns you define and review once, applied everywhere without drift.
It is not an AI product. It does not call an LLM at runtime. It is deterministic by design, which is precisely the point: your schema goes in, correct and consistent code comes out, according to rules your team agreed on, auditable in a way that probabilistic generation never quite is.
If you're building a business application of small to mid size - not a platform serving a hundred thousand concurrent users, just a real application that needs to work correctly and be maintainable by a small team - Reepolee is built for exactly that context. The goal was always to make the boring, necessary, repetitive parts of that work disappear so that the genuinely interesting work gets all the attention it deserves.
Use the LLM to build better generators. Use the generators to build consistent software. That's the loop worth investing in.