TAI BUI
Back to curriculum
LearnPython

A/B Testing LLM Features — GrowthBook, Statsig, and the Vibes Problem

Evals tell you whether the model can do the job. An A/B test tells you whether users care, and you need both before you ship. The things worth testing are the prompt wording, the model choice (GPT-4 vs GPT-3.5 vs OSS, weighing accuracy against cost and latency), and the generation parameters. Reported results include a chatbot reward-model variant with +70% conversation length and +30% retention, Nextdoor subject lines with +1% CTR after reward-function refinement, and Khan Academy's Khanmigo iterating on a latency-versus-math-accuracy trade. For tooling, Statsig (acquired by OpenAI for $1.1B in September 2025) bundles sequential testing, CUPED, and feature flags. GrowthBook is open-source and warehouse-native, with Bayesian, Frequentist, and Sequential engines, CUPED, SRM checks, and Benjamini-Hochberg and Bonferroni corrections. Pick based on how much you want to write warehouse SQL and whether "acquired by OpenAI" matters to your organization.

TIME: ~60 minutesPREREQUISITES: Phase 17 · 13 (Observability), Phase 17 · 20 (Progressive Deployment)

Learning Objectives

  • Distinguish evals ("can the model do the job") from A/B tests ("do users care").
  • Enumerate three testable axes (prompt, model, parameters) and pick the metric for each.
  • Explain CUPED, sequential testing, and Benjamini-Hochberg multiple-comparison corrections.
  • Pick Statsig or GrowthBook based on warehouse-SQL posture and corporate acquisition stance.

The Problem

You hand-tuned a system prompt and it feels better, so you ship it. Conversion changes by noise, and you blame the metric. Or you shipped a new model and conversion didn't move. Did the model degrade, or was the change too small to detect? You can't tell, because you shipped without an A/B.

Evals tell you whether the model can do a task on a labeled set. They say nothing about whether users prefer the output. Only a controlled online experiment answers that, and only if it has enough power, accounts for non-determinism, and corrects for multiple comparisons.

Warm-up0/3
1. A canary serves a new prompt to 5% of traffic. Which signal from your observability stack best tells you it is safe to widen the rollout?Warm-up
A canary at 5% of traffic with three dashboard metric tiles, error rate, P99 latency and cost per request, none marked good or bad, plus three other facts: the diff was reviewed before launch, one sampled request's output looked shorter, and no one has complained in the first minute. A line asks which signal best tells you it is safe to widen the rollout.
Setup: all four candidate signals the stem offers, none resolved. Which one actually tells you it is safe is left open.
2. Why do you track P99 latency for an LLM endpoint instead of only the mean?Warm-up
An illustrative latency histogram with a long right tail, most requests fast and a few much slower, with a mean marker over the bulk and a P99 marker out in the tail. A line asks why track P99 instead of only the mean.
Setup: an illustrative distribution shape with both reference points marked, no explanation of what either one tells you.
3. Two versions of a web page are shown to visitors, and each visitor's version is picked by a random draw. What is the main benefit of assigning at random?Warm-up
Visitors flowing through an unlabeled random draw into either Version A or Version B, with a note that each visitor's version is picked by that draw. A line asks what the main benefit of assigning at random is.
Setup: the random draw itself, with no outcome measured and no benefit named. What the benefit actually is stays open.
Check: The Problem0/1
1. You shipped a new model with no experiment and conversion did not move. Why can you not conclude the model is no worse?Analyze
A card stating a new model shipped with no A/B test, and that conversion did not move afterward. A line asks why you can't conclude the model is no worse.
Setup: only the given facts, no experiment run and no change observed. Why that is not conclusive stays open.

The Concept

Evals vs A/B tests

Evals are offline. You have a labeled set and a judge (a rubric, an LLM-as-judge, or a human), and the question is whether the output is correct, helpful, or safe on that fixed distribution.

An A/B test is online. Live users are randomized into variants, and the question is whether the new variant moves the user-level metric that matters.

You need both. Evals catch regressions before anyone is exposed, and the A/B confirms the product impact afterward.

What to test

  1. Prompt engineering: wording, system-prompt structure, examples. Metric: task success, user retention, cost/request.
  2. Model selection: GPT-4 vs GPT-3.5-Turbo vs Llama-OSS. Metric: accuracy on the task, cost/request, and latency P99, so it is multi-objective.
  3. Generation parameters: temperature, top-p, max_tokens. Metric: task-specific, usually output diversity against determinism.

CUPED (variance reduction)

CUPED stands for Controlled-experiments Using Pre-Experiment Data. You regress out the part of the post-period variance that the pre-period explains, then compare the adjusted values. Typical variance reduction is 30-70%, which raises your effective sample size without collecting any more users.

Both Statsig and GrowthBook implement it.

Sequential testing

Classical A/B testing assumes a fixed sample size, so peeking at the result early inflates the false-positive rate. Sequential tests control that rate under repeated looks. Always-valid procedures (mSPRT, Howard's confidence sequences) let you stop early when one variant is clearly winning.

Multiple-comparison corrections

Run 20 A/B tests at 95% confidence and you expect about one false positive by chance. Bonferroni tightens α per test. Benjamini-Hochberg controls the false-discovery rate instead, which is less conservative. GrowthBook implements both.

SRM (sample ratio mismatch)

An assignment hash randomizes users into variants. If a 50/50 split delivers 47/53, something upstream is broken, and the SRM check flags it. Both platforms implement it.

Statsig vs GrowthBook

Statsig:

  • Acquired by OpenAI for $1.1B (September 2025). Hosted SaaS.
  • Sequential testing, CUPED, held-out populations.
  • Bundles feature flags, experimentation, and observability.
  • Best fit: a team that wants one product and doesn't mind OpenAI ownership.

GrowthBook:

  • Open-source (MIT) and warehouse-native, reading from Snowflake, BigQuery, or Redshift directly.
  • Bayesian, Frequentist, and Sequential engines.
  • CUPED, SRM, Bonferroni, and BH corrections.
  • Self-host or managed cloud.
  • Best fit: a warehouse-SQL shop where the data team owns the metric layer and wants OSS.

Non-determinism complicates power

The same prompt produces different outputs. Standard power calculations assume IID observations, and with LLM non-determinism your effective sample size ends up below the nominal one. Multiply the required sample size by roughly 1.3-1.5x as a safety margin.

Real case outcomes

  • Chatbot reward model variant: +70% conversation length, +30% retention.
  • Nextdoor subject lines: +1% CTR after reward-function refinement.
  • Khan Academy Khanmigo: iterating on a latency-versus-math-accuracy trade.

The anti-pattern: shipping on vibes

Most senior engineers can name a feature that shipped because it "felt better," with no A/B behind it. Plenty of those regressed product metrics that nobody noticed for months. The A/B is what forces the question.

Numbers to remember

  • Statsig acquired by OpenAI: $1.1B, September 2025.
  • GrowthBook: open-source MIT, with Bayesian, Frequentist, and Sequential engines.
  • CUPED variance reduction: 30-70%.
  • LLM non-determinism: add a 30-50% sample-size buffer.
Check: The Concept0/29
1. What is an eval, as the term applies to an LLM feature?Define
A card naming eval and placing it alongside an A/B test as one of two ways this lesson checks an LLM feature. A line asks what an eval is.
Setup: the term, among the one sibling way of checking a feature. What an eval actually is stays open.
2. What is an A/B test of an LLM feature?Define
A card naming A/B test and setting it against an eval as the second way this lesson checks an LLM feature. A line asks what an A/B test is.
Setup: the term, set against its one sibling way of checking a feature. What an A/B test actually is stays open.
3. What does CUPED do for an experiment?Define
A card naming CUPED and listing it among the experiment techniques this lesson covers, alongside sequential testing and multiple-comparison corrections. A line asks what CUPED does for an experiment.
Setup: the term, among its sibling techniques. What CUPED actually does stays open.
4. What is a sequential test?Define
A card naming sequential test and setting it against a classical fixed-sample test as the two designs this lesson compares. A line asks what a sequential test is.
Setup: the term, set against its sibling design. What a sequential test actually is stays open.
5. What is the multiple comparison problem?Define
A card naming the multiple comparison problem and noting it comes up when many A/B tests run at once, addressed by Bonferroni and Benjamini-Hochberg. A line asks what the problem is.
Setup: the term, among the corrections that address it. What the problem actually is stays open.
6. What is the Bonferroni correction?Define
A card naming Bonferroni and setting it against Benjamini-Hochberg as the two corrections this lesson names. A line asks what the Bonferroni correction does.
Setup: the term, set against its sibling correction. What Bonferroni actually does stays open.
7. What is the Benjamini-Hochberg correction?Define
A card naming Benjamini-Hochberg and setting it against Bonferroni as the second correction this lesson names. A line asks what the Benjamini-Hochberg correction is.
Setup: the term, set against its sibling correction. What it actually is stays open.
8. What is SRM in an experiment?Define
A card naming SRM and listing it among the checks this lesson covers for a live experiment, alongside CUPED and sequential testing. A line asks what SRM is in an experiment.
Setup: the term, among its sibling checks. What SRM actually is stays open.
9. What is Statsig?Define
A card naming Statsig and setting it against GrowthBook as the two experimentation platforms this lesson compares. A line asks what Statsig is.
Setup: the name, set against its sibling platform. What Statsig actually is stays open.
10. What is GrowthBook?Define
A card naming GrowthBook and setting it against Statsig as the second platform this lesson compares. A line asks what GrowthBook is.
Setup: the name, set against its sibling platform. What GrowthBook actually is stays open.
11. What is mSPRT?Define
A card naming mSPRT among the always-valid sequential procedures this lesson mentions. A line asks what mSPRT is.
Setup: the name, among the general class it belongs to. What mSPRT actually is stays open.
12. A teammate says the eval suite passed, so the new prompt does not need an A/B test. What is the flaw?Explain
A card stating a teammate's claim: the eval suite passed on its labeled set, so the new prompt does not need an A/B test. A line asks what the flaw is.
Setup: only the teammate's claim and its stated reasoning. What the flaw actually is stays open.
13. Why do teams run evals before an A/B test rather than relying on only one of them?Explain
A card naming the order teams use, evals first on a fixed labeled set, an A/B test afterward on live users. A line asks why run both instead of relying on only one.
Setup: only the order the two run in. Why both are needed stays open.
14. Why is testing the model choice (GPT-4 vs GPT-3.5-Turbo vs an open model) called multi-objective?Explain
A card naming a model-choice test, GPT-4 versus GPT-3.5-Turbo versus an open model, noting that more than one outcome is measured at once. A line asks why this is called multi-objective.
Setup: only that more than one outcome is measured, not which ones. Why that makes it multi-objective stays open.
15. Which metric fits a test of generation parameters such as temperature, top-p, and max_tokens?Explain
A card naming a test of generation parameters, temperature, top-p and max_tokens. A line asks which metric fits this test.
Setup: only the parameters under test. Which metric fits stays open.
16. Why can you stop an always-valid sequential test early on a clear winner, but not a classical fixed-sample test?Explain
A card naming two test designs, an always-valid sequential procedure and a classical fixed-sample test, with no mechanism given for either. A line asks why one can stop early on a clear winner but not the other.
Setup: only the two named designs. Why one allows an early stop and the other does not stays open.
17. Why is Benjamini-Hochberg described as less conservative than Bonferroni?Explain
A card naming the two multiple-comparison corrections, Bonferroni and Benjamini-Hochberg, with no mechanism given for either. A line asks why Benjamini-Hochberg is described as less conservative.
Setup: only the two names. Why one is less conservative than the other stays open.
18. Why does CUPED raise your effective sample size without collecting any more users?Explain
Pre-period data from the same users flowing through an unlabeled step into an adjusted post-period metric, with a note that no additional users are collected. A line asks why this raises the effective sample size.
Setup: the pre- and post-period data and the fact that no new users are added. What the blank step actually does stays open.
19. Why should the sample size for an LLM feature test be padded by roughly 1.3-1.5x?Explain
The same prompt run twice producing a different output each time. A line asks why the required sample size should be padded by roughly 1.3 to 1.5x.
Setup: only the given fact that outputs vary run to run. Why that calls for a padded sample size stays open.
20. Why does a team's stance on corporate ownership matter when choosing between Statsig and GrowthBook?Explain
A card naming Statsig and GrowthBook as the two platforms being chosen between, with a note that one factor beyond features is who owns the company behind each, no ownership details given. A line asks why a team's stance on that matters.
Setup: only that ownership is one factor, with no detail about either company's actual ownership. Why that matters stays open.
21. You run 20 independent A/B tests at 95% confidence and none of the variants truly differ. What should you expect, and what helps?Apply
A card stating 20 independent A/B tests run at 95% confidence where none of the variants truly differ. A line asks what you should expect, and what helps.
Setup: only the given count and confidence level, and that none truly differ. What to expect and what helps stay open.
22. A power calculation says you need 40,000 users per arm to detect a prompt change, and the feature calls an LLM with non-trivial temperature. What do you plan for?Apply
A card stating a power calculation that says 40,000 users per arm are needed, for a feature that calls an LLM with non-trivial temperature. A line asks what you plan for.
Setup: only the given 40,000 figure and the note about temperature. What to actually plan for stays open.
23. You target a 50/50 split but the dashboard shows 47/53. What does this point to?Analyze
Four bars, a planned 50/50 split next to the actual 47/53 split the dashboard shows, all bars the same color. A line asks what this points to.
Setup: the given planned and actual splits, with no cause named. What it points to stays open.
24. A team checks a fixed-sample test every morning and ships the first time it looks significant. Many of these wins vanish after launch. What is the most likely cause?Analyze
A card describing a team that checks a fixed-sample test every morning and ships the first time it looks significant, with many of those wins vanishing after launch. A line asks what the most likely cause is.
Setup: only the given habit and its outcome. What causes it stays open.
25. A feature shipped because it felt better, and product metrics quietly regressed for months. Which practice would have caught it?Analyze
A card describing a feature shipped on it felt better with no A/B test, where product metrics regressed unnoticed for months. A line asks which practice would have caught it.
Setup: only the given outcome, no candidate practice named. Which practice would have caught it stays open.
26. Your data team owns metric SQL in Snowflake, wants open source, and does not want experiment data tied to OpenAI. Which platform fits and why?Design
A card listing a data team's three given wants, owning metric SQL in Snowflake, wanting open source, and not wanting experiment data tied to OpenAI. A line asks which platform fits, and why.
Setup: only the three given wants, no platform named. Which platform fits stays open.
27. You plan an A/B test of a larger versus a smaller model for a support bot. Which metric plan fits the lesson?Design
A card naming an A/B test for a support bot comparing a larger model against a smaller model, with no metric named. A line asks which metric plan fits the lesson.
Setup: only the given comparison, no metric named. Which metric plan fits stays open.
28. You will test 20 prompt variants on modest traffic, want early stops on clear wins, and want to limit false positives. Which plan fits?Design
A card describing a test of 20 prompt variants on modest traffic, wanting early stops on a clear winner and wanting to limit false positives across all 20 tests. A line asks which plan fits.
Setup: only the given count and the two given wants. Which plan fits stays open.
29. A small team wants flags, experimentation, and observability in one product, and it does not mind OpenAI owning the vendor. Which platform fits the lesson's guidance?Design
A card describing a small team that wants flags, experimentation and observability bundled in one product, and does not mind OpenAI owning the vendor. A line asks which platform fits the lesson's guidance.
Setup: only the given wants, no platform named. Which platform fits stays open.

Use It

code/main.py simulates a sequential A/B test with fixed and sequential boundaries. It shows how the sequential bound lets you stop early when the effect is large.

Check: Use It0/6
1. In main.py, fixed_sample_size returns 40,000 for some baseline and lift. What does the script print as the LLM-adjusted figure?Apply
A flow from fixed_sample_size returning 40,000 into an LLM-adjusted figure box with the buffer applied, no multiplier shown. A line asks what the script prints as the LLM-adjusted figure.
Setup: the given 40,000 and that a buffer is applied, with no multiplier shown. The printed adjusted figure stays open.
2. simulate runs with p_a=0.03 and p_b=0.0315 (a 5% lift) and a cap of 300,000 users. What does sequential_stop_at hold?Apply
A table of simulate's own given parameters for a 5% lift, p_a 0.03, p_b 0.0315, a 300,000-user cap and checks beginning once each arm passes 100 users, with a note that each check compares |z| to a growing threshold. A line asks what sequential_stop_at holds.
Setup: the given parameters for this one scenario, not yet run. What sequential_stop_at ends up holding stays open.
3. In simulate, the bound is sqrt(2 * log(1/0.05) + log(n_total)). As more users accumulate, what happens to the |z| needed to stop?Apply
The sequential bound's own formula from main.py, threshold equals the square root of 2 times log of 1 over 0.05 plus log of n_total, with no plot of its shape. A line asks what happens to the |z| needed to stop as n_total grows.
Setup: the bare formula, matching what the stem already states. How it actually behaves as n_total grows stays open.
4. You call fixed_sample_size(0.03, 0.05, alpha=0.01, power=0.9). How does the result compare with the call using the defaults?Apply
Two calls to fixed_sample_size, one with defaults and one with alpha 0.01 and power 0.9 passed explicitly, with no result shown for either. A line asks how the second result compares with the first.
Setup: the two calls as given, not yet run. How their results compare stays open.
5. The lesson covers CUPED, so a reader expects main.py to show a variance-reduced result. What do they find?Apply
The real top-level functions defined in main.py, in file order: z_statistic, fixed_sample_size, simulate, and main. A line says a reader expects a CUPED-adjusted result somewhere in here and asks what they find.
Setup: the real function list, confirmed from the file. Whether any of them implements CUPED stays open.
6. The 5% lift simulation reports no stop at 300,000 users, and a teammate says the sequential bound must be broken. What is the best diagnosis?Analyze
A card stating that a 5% lift simulation reports no stop recorded within the 300,000-user cap, and that a teammate says the sequential bound must be broken. A line asks what the best diagnosis is.
Setup: only the given result and the teammate's claim. The actual diagnosis stays open.

Ship It

This lesson produces outputs/skill-ab-plan.md. Given a feature change, a workload, and a baseline, it picks the platform, the gates, and the sample size.

Author's Note

I'd run main.py before trusting any sample-size number in this lesson. It is stdlib Python, and it prints the fixed-sample size for a 3% baseline at 2%, 5%, and 10% lifts, then the same figure multiplied by 1.4 for the non-determinism buffer. The 1.4 is a constant in the script. It sits inside the 1.3-1.5x range above, but nothing in the code derives it.

The simulation is the part to read closely. It starts checking after 100 users per arm and stops when the z-statistic crosses sqrt(2 * log(1/0.05) + log(n)). On the 50% lift case it stops at 2,774 total users. On the 10% lift it runs to about 160,000 before stopping. On the 5% lift it never crosses the bound inside the 300,000-user cap and reports the stop as None. Early stopping pays off on large effects and gives you little on small ones, which is the trade you accept.

Two limits to keep in mind. The script has no CUPED code, so treat that section as concept only. And fixed_sample_size takes alpha and power arguments while hardcoding 1.96 and 0.84, so changing them does nothing. Exercise 1 is easiest to check if you fix that first.

Exercises

  1. Run code/main.py. For an expected 5% lift with baseline 3% conversion, what sample size to 80% power?
  2. Pick Statsig or GrowthBook for a healthcare-regulated on-prem customer.
  3. Design an A/B that tests GPT-4 vs GPT-3.5 on cost-per-resolved-ticket. What's the primary metric, guardrail metric, secondary?
  4. Your canary passes but A/B shows -1.2% conversion. Do you ship? Write the escalation criteria.
  5. Apply CUPED to a pre-period with 60% of the variance of post. Compute the effective-sample-size boost.

Key Terms

TermWhat people sayWhat it actually means
Eval"offline test"Labeled-set evaluation of model capability
A/B test"experiment"Live randomized comparison on users
CUPED"variance reduction"Pre-period regression to reduce variance
Sequential test"peek-ok test"Always-valid procedure allowing early stop
Multiple comparison"the family error"Running many tests inflates false positives
Bonferroni"tight correction"Divide α by number of tests
Benjamini-Hochberg"BH FDR"False-discovery-rate control, less conservative
SRM"bad split"Sample ratio mismatch; assignment bug
Statsig"OpenAI owned"Commercial all-in-one, acquired 2025
GrowthBook"the OSS one"MIT warehouse-native platform
mSPRT"sequential probability ratio test"Classical sequential procedure

Further Reading

Code

Ships With