Why Hardcoded Prompts Are the New Hardcoded Config
TL;DR
- A prompt in your codebase is configuration wearing a string literal's clothes — it changes far more often than the code around it.
- The costs show up as deploy-per-tweak, no version history, no rollback, and a bottleneck where only engineers can change customer-facing language.
- The industry already solved this shape of problem with config services and feature flags. Prompts are the same lesson, one layer up.
- Moving prompts behind a prompt registry takes an afternoon: your code fetches the active version at runtime instead of embedding it.
Every AI product starts the same way. Someone writes a prompt inside a Python file, wraps it in an f-string, and ships it. It works. The feature goes live. Nobody thinks about it again until the third time a teammate asks, in Slack, whether anyone still has the version of the summariser prompt that worked better last Tuesday.
That question is the moment a team discovers that prompts are not code. They look like code, they live in code, and they are reviewed like code — but they behave like configuration, and configuration in a codebase has a well-documented set of failure modes.
What is a hardcoded prompt?
A hardcoded prompt is any instruction sent to a language model that is stored as a literal in your application source. It might be a string constant, a template file in the repo, or a heredoc in a service class. The defining property is that changing the words requires changing the codebase.
SUMMARY_PROMPT = """You are a helpful assistant.Summarise the following support ticket in two sentences.Be concise and professional.Ticket: {ticket_body}"""def summarise(ticket_body: str) -> str: return llm.complete(SUMMARY_PROMPT.format(ticket_body=ticket_body))There is nothing wrong with this code. It is clear, testable, and obvious. The problem is not the code — it is the change rate of the thing inside it. Application logic changes when requirements change. Prompt wording changes when a customer complains about tone, when a model version shifts, when someone notices the output rambles on long tickets, or when a founder reads one poor summary on a Sunday.
When do hardcoded prompts break?
They break at predictable moments, and the symptoms are consistent enough to be a checklist. If more than two of these are true for your team, prompts have outgrown the repo.
A deploy for every wording change
Changing four words in a prompt should not require a pull request, a review, a CI run, and a production release. When it does, the real cost is not the pipeline minutes — it is that people stop making small improvements. A change that costs a deploy has to justify a deploy, so the marginal tweak never happens and quality plateaus.
No history you can actually read
Git technically records the change, but git history answers *what the file looked like*, not *which wording was live in production on the day that customer complained*. Those are different questions. Rolling back a prompt through git means reverting a commit and redeploying, which is a heavy instrument for a change that should take seconds.
Only engineers can iterate
This is the expensive one. The person best equipped to improve a support-triage prompt is usually the person who reads support tickets all day — and they cannot open a code editor. So they file a ticket, an engineer context-switches, and a two-minute wording change becomes a two-day round trip. Iteration speed collapses to the speed of the slowest handoff.
No safe way to compare two versions
Comparing prompt A against prompt B means running both against the same inputs and reading the outputs side by side. With prompts in code, that is a branch, a local harness, and a lot of copy-pasting into a terminal. Most teams simply skip it and change the prompt on instinct.
Why is this the same lesson as config and feature flags?
Web engineering already went through this exact arc, twice.
First with configuration. Database URLs, timeouts, and feature toggles started as constants in source. Then came environment variables, then config services, because operators needed to change runtime behaviour without a release cycle. The insight was that things which change on a different clock than the code should not ship on the code's clock.
Then with feature flags. Teams realised that deciding *whether* a feature is on is a product decision made continuously, often by people who do not write code, and often needing instant reversal. Flags moved that decision out of the binary and into a control plane with an audit trail and a kill switch.
Prompts have both properties, at once. They change on a product clock, not an engineering clock. They are edited by whoever understands the customer. They need instant rollback when a change degrades outputs. And they need history, because *when did this change and who changed it* is the first question asked after a regression.
What is a prompt registry?
A prompt registry is a system of record for your prompts. Each prompt has versions, one version is marked active, and your application asks for the active version at runtime instead of embedding it. Editing happens in a console rather than an editor, so anyone on the team can improve wording without touching a repository.
The practical difference is that the prompt stops being a build-time artefact and becomes a runtime one. Your deploy pipeline stops being in the path of a wording change. If you want the longer argument for why this becomes standard infrastructure, we made it in The Prompt Registry Is the New Config Service.
How do you move prompts out of the repo?
The migration is smaller than it sounds, because the shape of the call barely changes. You are replacing a constant with a fetch.
import os, requestsENGINE_ID = "42"def summarise(ticket_body: str) -> str: resolved = requests.post( f"https://api.promptengine.co.in/v1/engines/{ENGINE_ID}/active-prompt", headers={"Authorization": f"Bearer {os.environ['PROMPT_ENGINE_KEY']}"}, json={"variables": {"ticket_body": ticket_body}}, ).json()["data"] # The active version's messages, variables already filled in. return llm.complete(resolved["messages"])A few things follow from this that are worth naming, because they are the actual payoff:
- Wording changes stop being releases. Someone edits the active version in a console; the next request picks it up. No branch, no review queue, no deploy window.
- You get real version history. Each edit produces a version you can read, compare, and go back to — and you can see which one was live when.
- Non-engineers can iterate. The person closest to the customer edits the words that reach the customer. See A Prompt Registry Your Whole Team Can Use.
- Rollback is a click. Activating the previous version is the whole procedure.
Your application code is now shorter and more stable than it was, which is the tell that the abstraction is in the right place. The endpoint contract is documented in the API reference, and how variables get substituted is covered in the variables docs.
Doesn't this give up the benefits of version control?
It is a fair objection, and the honest answer is that you trade one kind of history for another that fits the artefact better. Git is superb at tracking code, where changes arrive in reviewed batches tied to releases. Prompts change continuously, often by people outside the engineering loop, and what you need is *which version is serving traffic right now* and *what did the previous one say*.
A registry answers those directly. Every edit creates a version, versions can be forked to try a variation without disturbing what is live, and activation is explicit — so there is always an unambiguous answer to which wording is in production. That is closer to how a config service handles change than how a monorepo does, which is the point.
It also helps to remember that prompt quality is empirical. Model providers are explicit that iteration against real outputs is the method — Anthropic's prompt engineering guide is largely a description of a feedback loop. Anything that lengthens that loop degrades prompt quality, and shipping a deploy to test a comma is a long loop.
Where does Prompt Engine fit?
Prompt Engine is a prompt registry built around getting this done quickly. You create an engine, write prompt versions in the Kitchen console, test them against multiple providers, activate the one you want, and call a single endpoint from your backend to fetch whatever is currently active. Forking lets you try a variation without touching the live version.
There are several good tools in this space and they optimise for different things — we compared the axes honestly in How to Choose a Prompt Management Tool. Prompt Engine's particular bet is that most teams want to be productive the same afternoon they sign up, without adopting a framework first. If that is the trade you want, the quickstart is the shortest path, and pricing starts free.
The migration is genuinely an afternoon. The habit change — treating prompt wording as something you tune continuously rather than something you ship — is what pays for it.
Frequently asked questions
- What does it mean to hardcode a prompt?
- Hardcoding a prompt means storing the instruction text as a literal in your application source — a string constant, template file, or heredoc in the repository. The defining trait is that changing the wording requires a code change and a deploy.
- Why are hardcoded prompts a problem?
- Because prompts change far more often than the code around them. Hardcoding produces a deploy for every wording tweak, no readable history of which version was live when, no fast rollback, and a bottleneck where only engineers can change customer-facing language.
- What is a prompt registry?
- A prompt registry is a system of record for prompts. Each prompt has versions, one is marked active, and your application fetches the active version at runtime rather than embedding it. It is the same idea as a config service, applied to prompt text.
- How long does it take to move prompts out of code?
- For a typical service it is an afternoon. You replace each prompt constant with a call that fetches the active version, move the wording into the registry, and delete the literal. The call site barely changes shape.
- Do I lose version history if prompts leave my repository?
- No — you trade git history for versioning designed for this artefact. Every edit creates a version you can read and compare, forking lets you try variations without disturbing what is live, and activation makes it unambiguous which wording is serving traffic.
- Can non-engineers safely edit production prompts?
- Yes, and it is usually the point. Edits produce new versions rather than overwriting what is live, so a change can be reviewed and activated deliberately, and rolling back to the previous version is a single action.
Keep reading
A Prompt Registry Your Whole Team Can Use
Iteration speed compounds when the person closest to the customer can change a prompt without filing a ticket. That is a tooling decision, not a process one.
The Prompt Registry Is the New Config Service — Why Every AI Product Needs One
Every maturing platform grows a layer for the config that changes fastest. For AI products, that config is the prompt — and the layer has a name.
How to Choose a Prompt Management Tool in 2026
Five axes that actually predict whether a prompt tool will fit your team — and an honest read on where the well-known options land on each.