Prompt regression
Prompt regression testing is how you find out whether editing a prompt has made the feature worse. A prompt is a piece of production configuration that anyone can edit in a text box, that has no type system, no compiler and no diff anybody can read, and that changes the behaviour of the whole feature. Regression testing it is therefore not optional — but it cannot be equality checks, because the output moves on its own. This page covers what a regression means when results are scored, what has to be pinned before any comparison is honest, how to tell a real change from sampling noise, and what should block a release.
- Compare
- Case by case
- Always pin
- Prompt, model, index
- Block on
- What used to pass
What a regression means when the answer is scored
In ordinary software a regression is unambiguous: a test that passed now fails. Here it needs defining, because a case can score 0.83 today and 0.79 tomorrow with nothing changed at all. The definition that works is per case and against a threshold: a case regressed when it passed its own criterion at the baseline and does not pass it now, measured across enough runs that sampling cannot explain the difference.
The diagram is the argument for this whole page. Both runs score thirteen out of sixteen, so a team reading the headline number would conclude the change did nothing and ship it. Case by case, two behaviours that used to work no longer do, and two others started working. Whether that is a good trade is a real question with a real answer — but it is a question, and the aggregate never asked it.
A comparison is only honest if everything else is pinned
The most common way a prompt experiment produces a wrong conclusion is that it was never a prompt experiment. Several things feed the output, they change on different schedules and by different hands, and unless each is fixed for the duration of the comparison you are attributing the sum of several changes to the one you happened to make.
| What must be pinned | What happens if it is not |
|---|---|
| The exact prompt text, in version control | Nobody can say what was actually running when the good result was recorded, so it cannot be restored. |
| The model version, never an alias | Your system upgrades itself in production with no diff, no review and no rollback — the one arrangement nothing else in your stack would tolerate. |
| Sampling parameters — temperature, top-p, seed where available | Run-to-run variance changes between the two sides of the comparison, and the difference you measured is the setting. |
| The retrieval index and its contents | A re-indexed corpus changes what the model sees. The prompt gets credit or blame for a document that arrived on Tuesday. |
| Tool schemas and their responses | A renamed argument silently removes a capability, and the symptom looks exactly like a worse prompt. |
| The judge model and its rubric | You changed the ruler. Every historical number becomes incomparable, usually without anyone noticing. |
The practical form of all this is to treat the prompt, the model pin, the retrieval index version and the tool schemas as one versioned artefact, and to record which version of that artefact produced every baseline. A prompt version on its own is not enough information to reproduce a result, and reproducing yesterday’s result is exactly what a regression suite has to be able to do.
Telling a real change from sampling noise
Even with everything pinned, the same case run twice can score differently, because generation samples from a distribution. Before comparing anything, measure how much your own numbers move when nothing changes: run the unchanged baseline three times and look at the spread. That spread is your noise floor, and any difference smaller than it is not a result, however much anyone wants it to be.
- Run each case several times — three is a workable minimum, five is better on a small set — and treat a case as passing only if it passes consistently rather than once.
- Set temperature to zero for evaluation runs where the product allows it. It does not make output deterministic, but it materially narrows the spread and makes small movements readable.
- Do the arithmetic on set size before believing a delta. On forty cases, one case is two and a half points, so a three-point move is one case changing its mind.
- Report the per-case diff as the primary artefact and the aggregate as a footnote, because the diff answers the question the aggregate cannot.
The gate: what runs, what blocks, what it costs
A regression suite that is not wired to a decision is a report. The arrangement that works treats a change to the prompt-model-index artefact exactly like a code change: it opens a pull request, the suite runs against it, and the result is a diff a reviewer reads before merging.
What blocks
Any protected case that regressed, any deterministic check failing, cost or latency outside budget. These are absolute and need no discussion.
What warns
An aggregate drop larger than the noise floor, or several regressions outside the protected set. A person decides, with the diff in front of them.
What is recorded
The full per-case result becomes the new baseline on merge, tagged with the artefact version. Tomorrow’s comparison needs today’s record.
What it costs
Ninety cases at three runs is a few minutes and a couple of dollars per pull request. Budget it explicitly, or somebody will quietly turn it off.
One drill deserves to be rehearsed rather than improvised: the model upgrade. A provider announces a new version and retires the old one on a date, and that is the single largest regression event an LLM feature will experience. Run the full suite against the new version while the old pin still works, read the per-case diff, fix what broke, and switch on a day you chose. Teams that discover this on the retirement date do the same work in an afternoon, with users watching.
Anti-patterns worth naming
- Editing the production prompt in an admin panel, which is a deployment with no diff, no review and no way back.
- Judging a change on the aggregate score, which is exactly the statistic that hides the cases that broke.
- Re-running only the results you dislike, which turns evaluation into selection and tunes the prompt to lucky seeds.
- Pinning to a moving alias, so the deployed system changes on the provider’s schedule rather than on yours.
- Keeping no baseline artefact, so "it used to work" is a memory rather than a file anybody can open.
When to use it
Use it when
- On every change to the prompt, the model pin, the retrieval index or the tool schemas — each is a release.
- With a per-case baseline kept as an artefact, so a comparison is a diff rather than a recollection.
- With a protected set that blocks a release on any regression, regardless of what the aggregate did.
- Ahead of a provider model retirement, run while the old pin still works and switched on a day you chose.
Avoid it when
- Comparing on the aggregate score alone, which is the statistic that conceals the cases that broke.
- Single-run comparisons on a small set, where one case changing its mind looks like a three-point improvement.
- Experiments where the index, the tool schemas or the judge changed at the same time as the prompt.
- A suite that only reports, since a regression nobody is required to act on is a regression that ships.
Found this useful?
Share it with someone who is working on the same problem.