Running LLMs in production is no longer a matter of a few API calls. Change a prompt and output quality might drop 15% or climb 22% — but if you don't notice, deployment becomes randomness. Prompt versioning and A/B testing bring software deployment discipline to LLM operations. This piece explains how to use evaluation frameworks like Promptfoo and LangSmith to make prompt changes measurable.

Prompt change is not deployment

In classical software engineering, when a function changes, unit tests, integration tests, and canary deployments kick in. In LLM operations, most teams edit the prompt in a plain text file, run a few manual tests, and ship to production. The result: user sentiment drops 8% but nobody connects the dots.

The problem is this: LLM output is non-deterministic. The same prompt yields different responses, which makes single-example testing meaningless. Without a versioning system, you can't answer "was the old prompt better or the new one?" A git commit isn't enough either — you can't extract semantic differences from the commit message.

The solution: treat every prompt change as a version, run your eval set before and after the change, compare metrics. This discipline delivers two things: regression detection (whether the new prompt breaks old tasks) and improvement measurement (whether your target metric actually increases).

How to build an evaluation pipeline

An evaluation pipeline has three components: eval set, eval metric, and runner. The eval set is a list of inputs you'll send to the LLM and the expected outputs (or output properties). In JSON, it looks like this:

[
  {
    "input": "Summarize the 2025 Q1 revenue trend",
    "expected_topics": ["revenue", "growth", "quarter"],
    "expected_sentiment": "neutral"
  },
  {
    "input": "Explain why churn rate is rising",
    "expected_topics": ["churn", "retention"],
    "expected_sentiment": "analytical"
  }
]

You can build the eval set manually (by sampling from production logs) or synthetically (by asking another LLM to generate 50 query variations for your prompt). What matters is that the set covers edge cases — long inputs, ambiguous questions, multiple languages.

The eval metric defines how you score LLM output. Two common types: rule-based (checking for specific words in the output) and LLM-as-judge (asking another LLM to score on a 1–5 scale: "Does this output answer the question correctly?"). LLM-as-judge is more flexible but slower and costlier. For a balance of speed and accuracy, combine rule-based checks with lightweight classifiers (like BERT-based sentiment models).

The runner takes the eval set, runs both old and new prompts for each input, scores the outputs with your metric, and produces a diff table. Promptfoo does this with promptfoo eval from the terminal:

promptfoo eval \
  --prompts prompts/v1.txt prompts/v2.txt \
  --providers openai:gpt-4 \
  --tests evals/summarization.json \
  --output results.json

The output shows which prompt performs better on each test case. If your new prompt improves the metric on 80% of the eval set, you're ready to deploy. Otherwise, you have regression — revisit the prompt.

A/B testing: running two prompts in parallel in production

The eval pipeline gives offline results — no real user data. To measure which prompt performs better in production, A/B test both prompts live. This requires traffic splitting and metric collection infrastructure.

Traffic splitting is straightforward: hash the user_id or session_id in incoming requests, use modulo to route. For instance, if hash(user_id) % 100 < 50, send to prompt A; otherwise, prompt B. This creates a 50–50 split. Critical: the same user should see the same prompt on every request (sticky assignment) — otherwise user experience becomes inconsistent.

For metric collection, attach metadata to the LLM response: prompt_version, latency, token_count. This data flows to your data warehouse (BigQuery, Snowflake). This is where Roibase's Data Analytics & Insight Engineering pipeline steps in — you can join LLM logs with other event data (user actions, conversions, churn) to measure downstream impact of the prompt change.

What metrics do you track in A/B testing? Three categories:

Metric typeExampleTarget
QualityLLM-as-judge score, hallucination rateHigh
CostToken count, API costLow
DownstreamConversion rate, user engagementHigh

For example, prompt B might improve the LLM-as-judge score 12% versus prompt A, but use 35% more tokens — that's a tradeoff. If downstream conversion shows no difference, prompt A is more efficient.

LangSmith and observability

LangSmith is an LLM observability platform built by the LangChain team. Beyond evaluation, it captures production traces, visualizes prompt chains, and shows where latency spikes. Especially in multi-step LLM workflows (RAG + summarization + JSON parsing), debugging is critical.

Send traces to LangSmith using the SDK:

from langsmith import Client
client = Client(api_key="...")

with client.trace(name="summarize_revenue"):
    result = llm.invoke(prompt)
    client.log_metric("token_count", result.usage.total_tokens)

Every trace appears in the LangSmith UI, with full input/output/metadata logging. If you have multiple prompt versions, you can open a comparison view. In the UI you'll see insights like "prompt v2 produces 8% longer outputs on average than v1, but 3% lower latency."

LangSmith also provides a playground — change the prompt and test against multiple inputs with one click. This creates a fast feedback loop for both prototyping and regression testing. But remember: testing in the playground doesn't replace production A/B testing; it's just a first filter.

The second benefit of prompt versioning: rollback

When a deployment goes wrong, rollback is critical. In LLM operations, rollback means reverting to the previous prompt version. To do that, you need versioning infrastructure.

Simple approach: store each prompt in git as a separate file (prompts/summarization_v3.txt). A deployment script tracks which version is in production in a config file:

# config/production.yaml
prompts:
  summarization: v3
  classification: v2

To rollback, change summarization: v2 and trigger deployment. But this is manual and slow in an incident. A more sophisticated approach: use feature flags (LaunchDarkly, Unleash) to switch prompt versions at runtime without redeploying.

This is where Roibase's First-Party Data & Measurement Architecture practices come in — you need to correlate prompt changes with downstream events (conversion, churn) so your rollback decision is data-driven. If churn rate jumps 4% within six hours of deploying the new prompt, that's your signal to rollback.

Edge case: multilingual prompt versioning

If your LLM application runs in multiple languages (TR, EN, DE), maintain separate prompt versions per language. A prompt that works well in English might not deliver the same tone in Turkish.

Solution: organize prompt files by language code:

prompts/
  summarization/
    en_v3.txt
    tr_v3.txt
    de_v3.txt

Your eval set should also be language-specific — Turkish test cases should have Turkish output expectations. Run A/B tests by language, because user behavior differs across regions. Don't forget to add language segment to metric aggregation.

Another caution: in multilingual prompts, context length varies by language — Turkish sentences are roughly 12% longer by token count. This risks hitting token limits. Add token count checks to your eval pipeline and warn on threshold breaches.

Practical first step: build your first eval set

To implement the system described here, start small: a minimal eval set of 20–30 real user queries. Open your production logs, pick the most common queries, and define expected output properties for each (accuracy, tone, length).

Then set up Promptfoo or LangSmith, run your current prompt against this set, and take a baseline score. Now make a small prompt change (e.g., add "respond concisely and clearly"), run eval again, and compare scores. If regression is under 5%, deploy the change.

Once this loop is automated, your prompt iteration speed triples. Because now you answer "is this change good or bad?" with numbers, not guesses.