Prompt Versioning in Production: The Discipline Nobody Talks About
A prompt update goes out to a document classification agent that has run cleanly for months. On the evaluation set of 200 representative documents, accuracy went up, so it ships. Over the next two weeks, the false positive rate on one class of edge case, a class the eval set never represented, climbs several times over. The prompt is better on average and much worse on a tail nobody could see, because everyone was measuring averages. Finding the regression and rolling back takes two weeks. The way to avoid this is to treat prompt changes the way you treat code changes.
Why prompts are not like other configuration
Configuration changes in traditional software are predictable. Changing a timeout from 30 seconds to 60 seconds has a well-understood effect. Changing a prompt is different. A prompt is a natural language instruction to a statistical model. The effect of changing a single sentence can be nonlinear, can vary significantly across different input distributions, and can improve performance on common cases while degrading performance on rare ones.
This makes prompt changes more like code changes than configuration changes. They carry the same risk as a logic change in a function that handles a wide variety of inputs. You would not ship a logic change without testing it against a regression suite. You should not ship a prompt change without testing it against one either.
The evaluation set problem
An evaluation set is only useful if it represents the actual distribution of inputs your system will see in production. The problem is that evaluation sets are usually built from common cases, the clear examples that are easy to label and reason about. Tail cases (ambiguous documents, unusual formats, adversarial inputs, suppliers you have never seen before) are underrepresented.
The evaluation set is therefore biased toward the center of your input distribution, and a prompt that improves performance on the center can degrade performance on the tail without your evaluation set detecting it. Our March incident was exactly this: the prompt change included more specific instructions that improved handling of common document types and confused the model on ambiguous ones.
Maintain two evaluation sets: a core set of representative cases (250–400 items, balanced by document type and complexity) and a tail set of edge cases harvested from production: documents that were routed to human review, documents where confidence was low, documents that caused downstream errors. Prompt changes must not degrade performance on the tail set by more than 2% relative, regardless of what they do to core set performance.
Your evaluation set is only as good as its coverage of the failure modes you care about. Build it from production data, not from examples you constructed yourself. Real production data contains the edge cases your system will actually encounter. Synthetic examples contain the edge cases you thought of.
Version control for prompts
Prompts should live in version control alongside the code that uses them. Not in a database table. Not in an environment variable. In a file, in a repository, with a commit history.
The practical setup we use: prompts live in a /prompts directory as Markdown files (which render nicely and support comments). Each prompt file has a header with version number, last changed date, and a brief description of what changed and why. Prompt files are loaded at runtime from the file system, not hardcoded. This means: you can see the full history of every prompt in git log, diff between versions is readable, rollback is a one-line git command, and code review applies to prompt changes the same way it applies to function changes.
Our take
invoice_classifier_v1.md, invoice_classifier_v1.1.md (minor improvement to instructions), invoice_classifier_v2.md (major rewrite). The version number is included in every log entry so that when you look at the accuracy metrics for a given week, you know which prompt version was running. It sounds trivial. Without it, debugging a regression means cross-referencing deployment logs with performance metrics in two separate systems.Staged rollouts for prompt changes
The same staged rollout discipline that applies to code deployments should apply to prompt changes. The mechanism is straightforward: route a percentage of traffic to the new prompt version, compare performance metrics to the current version, and complete the rollout only if performance holds or improves.
For a document processing agent, sensible rollout stages are: 5% of traffic for 48 hours, expand to 20% for 72 hours, expand to 100% if metrics are within tolerance. The metrics to compare: accuracy on labeled outputs (where we have ground truth), confidence score distribution (a prompt change that shifts confidence scores upward without corresponding accuracy improvement is suspicious), error rate by document type, and exception routing rate (the percentage of documents sent to human review, where a significant change means the model is handling uncertainty differently).
For agentic systems where it is harder to measure accuracy directly, we compare: task completion rate, tool call patterns (does the new prompt cause different tool usage sequences?), and human override rate (how often does a human correct or override the agent's output). These are proxies, but they are proxies that are visible in production logs without requiring labeled data.
The rollback infrastructure
Prompt rollback should be a one-minute operation. If your rollback procedure involves coordinating a deployment, editing a database record, or getting another engineer involved, it is too slow. Production incidents do not wait for deployment processes.
Use a feature flag for prompt version selection: the active prompt version for each agent is controlled by a configuration value that can be changed without a deployment. Rollback is changing that value from v1.3 to v1.2 in a config panel. Changing it takes 30 seconds. The change takes effect on the next request. Being able to roll back immediately, instead of after a deployment cycle, is the difference between a 30-minute incident and a 4-hour one.