The Peeking Problem
The Peeking Problem
Peeking is the practice of checking experiment results before the planned sample size is reached and stopping the experiment if the result is statistically significant. It is one of the most common and most damaging mistakes in A/B testing.
Why Peeking Inflates False Positives
A standard hypothesis test controls the false positive rate at a single point in time. When you run a test at α = 0.05 with a fixed sample size, you accept a 5% chance of a false positive. This guarantee holds only if you look at the data exactly once.
When you peek — checking the p-value every day, for example — you are running multiple tests. Each peek is an opportunity to stop and declare significance. The more you peek, the more opportunities you have for a false positive.
Consider an experiment with a true null hypothesis (no effect). You check the p-value daily for 14 days. On each day, there is a 5% chance of a false positive. The probability of at least one false positive across 14 independent tests is:
P(at least one false positive) = 1 - (1 - 0.05)^14 = 1 - 0.488 = 0.512
A 51% false positive rate. More than half the time, you would conclude there is an effect when there is none.
The Mathematics of Peeking
The p-value under the null hypothesis is uniformly distributed between 0 and 1. This means that at any point in time, P(p < 0.05) = 0.05. But the p-value is not independent across time — it is a random walk that drifts as data accumulates.
The probability that the p-value crosses 0.05 at some point during the experiment is much higher than 5%. This is because the p-value can cross 0.05, come back above, cross again, and so on. Each crossing is a false positive opportunity.
import numpy as np
from scipy import stats
np.random.seed(42)
num_simulations = 10000
num_peeks = 14
false_positive_rate = 0.0
for _ in range(num_simulations):
# Simulate a true null: no difference between groups
n_per_group = 5000
control = np.random.binomial(1, 0.10, n_per_group)
treatment = np.random.binomial(1, 0.10, n_per_group)
# Peek daily (simulate by checking at fractions of the data)
for day in range(1, num_peeks + 1):
fraction = day / num_peeks
n = int(n_per_group * fraction)
c = control[:n]
t = treatment[:n]
_, p_value = stats.ttest_ind(t, c)
if p_value < 0.05:
false_positive_rate += 1
break
print(f"False positive rate with {num_peeks} peeks: {false_positive_rate/num_simulations:.3f}")
This simulation shows that peeking 14 times inflates the false positive rate from 5% to approximately 30-50%, depending on the correlation structure.
Why People Peek
Peeking is natural. You are excited about the experiment. You want to know if it is working. You check the dashboard and see p = 0.03. You stop the experiment and declare victory.
The problem is that p = 0.03 on day 3 does not mean the same thing as p = 0.03 on day 14. Early p-values are noisy. A p-value of 0.03 on day 3 might be 0.30 on day 7 and 0.01 on day 14. The early significance is often a fluke.
The Only Safe Peek
There is exactly one safe way to peek: use a sequential testing procedure that adjusts the significance threshold to account for the number of looks. This is the subject of the next chapter.
Without a sequential procedure, the only safe approach is to commit to a fixed sample size and a single analysis at the end. No peeking. No early stopping. No exceptions.
Sequential Testing with Alpha Spending
Sequential Testing with Alpha Spending
Sequential testing allows you to peek at experiment results while controlling the false positive rate. The key idea is to spend your alpha budget carefully across multiple looks, so that the total false positive rate never exceeds the nominal level.
The Alpha Budget
Think of α = 0.05 as a budget. In a fixed-sample test, you spend the entire budget at one point in time. In a sequential test, you allocate portions of the budget to each interim analysis. The sum of all allocations must not exceed 0.05.
The allocation is defined by an alpha spending function α*(t), where t is the fraction of the total sample size observed so far. The spending function determines how much alpha you can use at each look.
Common Spending Functions
O'Brien-Fleming spending: Conservative early, liberal late. Most of the alpha is spent at the final analysis. This is appropriate when you want to avoid stopping early based on noisy data.
α*(t) = 2 - 2 × Φ(z_{α/2} / √t)
Pocock spending: Equal alpha at each look. More aggressive early stopping. This is appropriate when you want to stop as soon as possible.
α*(t) = α × ln(1 + (e - 1) × t)
Lan-DeMets spending: A flexible family that approximates O'Brien-Fleming or Pocock depending on parameters.
How Alpha Spending Works in Practice
Suppose you plan 4 interim analyses at 25%, 50%, 75%, and 100% of the sample size. You use O'Brien-Fleming spending with α = 0.05.
| Look | Fraction t | Cumulative alpha | Threshold (z-value) |
|---|---|---|---|
| 1 | 0.25 | 0.0000 | 4.05 |
| 2 | 0.50 | 0.0015 | 2.96 |
| 3 | 0.75 | 0.0096 | 2.36 |
| 4 | 1.00 | 0.0500 | 1.96 |
At the first look, you need a z-value of 4.05 (p < 0.0001) to stop. This is extremely conservative — you will almost never stop early. At the final look, the threshold is the standard 1.96 (p < 0.05).
from scipy.stats import norm
import math
def obrien_fleming_threshold(look_fraction: float, alpha: float = 0.05) -> float:
z_alpha = norm.ppf(1 - alpha / 2)
threshold = z_alpha / math.sqrt(look_fraction)
return threshold
for t in [0.25, 0.50, 0.75, 1.00]:
z_threshold = obrien_fleming_threshold(t)
p_threshold = 2 * (1 - norm.cdf(z_threshold))
print(f"Look at {t*100:.0f}%: z = {z_threshold:.2f}, p = {p_threshold:.4f}")
Group Sequential Design
A group sequential design pre-specifies:
- Number of looks: How many times you will check the data.
- Timing of looks: At what fraction of the sample size each look occurs.
- Spending function: How alpha is allocated across looks.
- Stopping rules: Efficacy boundary (stop for success) and futility boundary (stop for failure).
The design produces a set of critical values — one for each look. If the test statistic exceeds the critical value at any look, you stop and declare significance.
Futility Stopping
Sequential testing also allows for futility stopping — stopping the experiment early because the treatment is unlikely to work. This is not about controlling false positives; it is about saving resources.
If the observed effect at an interim look is so small that even with the full sample size you would not detect it, you can stop for futility. This does not inflate the false positive rate because you are not declaring a positive result.
Futility boundaries are typically based on conditional power — the probability of detecting an effect given the data observed so far. If conditional power falls below 20%, stopping for futility is reasonable.
Practical Implementation
Most experiment platforms support sequential testing. The implementation typically:
- Pre-computes the critical values for each look based on the spending function.
- At each look, compares the test statistic to the critical value.
- Stops the experiment if the critical value is crossed.
- Reports the adjusted p-value and confidence interval.
If you are implementing sequential testing yourself, use the gsDesign library in R or the sequential package in Python. Do not try to implement alpha spending from scratch — the mathematics is subtle and errors are easy to make.
Always Valid Inference and E-Vals
Always Valid Inference and E-Vals
A newer approach to the peeking problem produces p-values that are valid at every point in time, without pre-specifying a spending function or a maximum sample size. These are called always valid p-values or e-values.
The Limitation of Group Sequential Designs
Group sequential designs require you to pre-specify the number of looks and their timing. If you deviate from the plan — add an extra look, change the timing — the error guarantees no longer hold.
In practice, experimenters often want flexibility. They want to check the data when a key stakeholder asks, not when the pre-specified schedule says. This flexibility breaks the group sequential guarantees.
E-Values: A Different Approach
An e-value is a non-negative random variable whose expected value under the null hypothesis is at most 1. You can think of it as a bet against the null: if the null is true, you expect to break even or lose money.
The key property of e-values is that you can multiply them across time and the product remains a valid e-value. This means you can peek as often as you want, combine the evidence, and always have a valid test.
E_combined = E_1 × E_2 × E_3 × ... × E_k
If the product exceeds 1/α, you reject the null at level α. This holds for any number of peeks, at any times, with any data-dependent stopping rule.
The E-Value for a Z-Test
For a z-test, the e-value at each look is:
E = exp(z × λ - λ²/2)
Where z is the test statistic and λ is a tuning parameter that controls the tradeoff between sensitivity to small and large effects.
import numpy as np
from scipy.stats import norm
def e_value(z: float, lambda_param: float = 1.0) -> float:
return np.exp(z * lambda_param - lambda_param ** 2 / 2)
# Simulate peeking with e-values
np.random.seed(42)
num_simulations = 10000
num_peeks = 20
alpha = 0.05
false_positives = 0
for _ in range(num_simulations):
n_per_group = 5000
control = np.random.binomial(1, 0.10, n_per_group)
treatment = np.random.binomial(1, 0.10, n_per_group)
e_combined = 1.0
for day in range(1, num_peeks + 1):
fraction = day / num_peeks
n = int(n_per_group * fraction)
c = control[:n]
t = treatment[:n]
_, p_value = stats.ttest_ind(t, c)
z = norm.ppf(1 - p_value / 2)
e_combined *= e_value(z, lambda_param=0.5)
if e_combined > 1 / alpha:
false_positives += 1
break
print(f"False positive rate with e-values ({num_peeks} peeks): {false_positives/num_simulations:.3f}")
Always Valid p-Values
An always valid p-value can be derived from an e-value:
p_always_valid = min(1, 1 / E)
This p-value is valid at every look, regardless of how many times you peek or when you peek. You can check it every hour, every day, or every week — the false positive rate is always controlled at α.
When to Use E-Values vs. Group Sequential
| Criterion | Group Sequential | E-Values |
|---|---|---|
| Pre-specified looks | Required | Not required |
| Flexible peeking | Not allowed | Allowed |
| Statistical power | Higher | Slightly lower |
| Implementation complexity | Moderate | Low |
| Familiarity in industry | High | Growing |
Use group sequential designs when you can commit to a pre-specified analysis schedule and want maximum power. Use e-values when you need flexibility and want guaranteed validity regardless of how you peek.
Designing Sequential Experiments
Designing Sequential Experiments
Choosing between a fixed-sample design and a sequential design is a business decision as much as a statistical one. This chapter provides a framework for making that choice.
When to Use a Fixed-Sample Design
Fixed-sample designs are appropriate when:
You can commit to not peeking. If your team has the discipline to wait for the full sample size, a fixed-sample design is simpler and more powerful.
The experiment is short. If the experiment runs for one week, the temptation to peek is lower, and the benefit of early stopping is smaller.
You need maximum power. Fixed-sample designs are more powerful than sequential designs at the same sample size because they do not spend alpha on interim looks.
The cost of a false positive is very high. If a false positive would lead to a costly engineering investment, the conservative nature of a fixed-sample design is valuable.
When to Use a Sequential Design
Sequential designs are appropriate when:
The experiment is long. If the experiment runs for months, the ability to stop early saves significant time.
The treatment has potential for serious harm. If the treatment could degrade the user experience, you want to stop as soon as you detect harm.
Traffic is limited. If you cannot reach the required sample size quickly, sequential designs allow you to stop early if the effect is large.
Stakeholders will peek regardless. If you cannot prevent peeking, use a sequential design that makes peeking safe.
Sample Size Inflation for Sequential Designs
Sequential designs require a larger maximum sample size than fixed-sample designs to achieve the same power. The inflation factor depends on the number of looks and the spending function:
| Number of looks | Inflation factor |
|---|---|
| 1 (fixed) | 1.00 |
| 2 | 1.01 |
| 4 | 1.04 |
| 8 | 1.08 |
| ∞ (continuous) | 1.15 |
The inflation is modest for a small number of looks. For 4 looks, you need only 4% more users than a fixed-sample design.
A Practical Sequential Testing Workflow
Define the maximum sample size using standard power analysis.
Inflate the sample size by the appropriate factor for your number of looks.
Choose a spending function. O'Brien-Fleming is the default choice — it is conservative early and powerful late.
Pre-compute the critical values for each look.
At each look, compare the test statistic to the critical value. Stop if the critical value is crossed.
Report the result using the sequential p-value or confidence interval.
Common Mistakes in Sequential Testing
Mistake 1: Peeking without a sequential procedure. This is the most common mistake. If you are going to peek, use a sequential procedure. If you are not going to peek, use a fixed-sample design. Do not peek in a fixed-sample design.
Mistake 2: Changing the spending function after seeing the data. The spending function must be chosen before the experiment starts. Changing it after seeing the data invalidates the error guarantees.
Mistake 3: Ignoring the futility boundary. If you only define an efficacy boundary, you may continue an experiment that is doomed to fail. Define both boundaries.
Mistake 4: Not accounting for the correlation between looks. The test statistics at different looks are correlated because they use overlapping data. Sequential procedures account for this correlation. Naive Bonferroni correction does not — it is too conservative.
The Bottom Line
Peeking without a sequential procedure is the single most damaging statistical error in A/B testing. It inflates the false positive rate from 5% to 30% or higher. The fix is simple: either commit to not peeking, or use a sequential testing procedure that makes peeking safe. There is no middle ground.
Practice Problems
You run an experiment with a true null hypothesis (no effect). You check the p-value daily for 10 days. Each day, you stop if p < 0.05. What is the approximate false positive rate? Use the formula P(at least one false positive) = 1 - (1-α)^k for independent tests, and explain why the actual rate is even higher.
Solution
Using the independent approximation: P(at least one false positive) = 1 - (1 - 0.05)^10 = 1 - 0.599 = 0.401, or approximately 40%.
However, the actual false positive rate is even higher than 40% because the p-values are not independent across days. The p-value on day 2 is correlated with the p-value on day 1 because they use overlapping data. This correlation means the p-value can cross the 0.05 threshold multiple times, creating more false positive opportunities than the independent approximation suggests.
In practice, simulations show that peeking 10 times inflates the false positive rate to approximately 25-35%, depending on the sample size and the correlation structure. The exact rate depends on the specific design, but it is always substantially higher than the nominal 5%. You are running an experiment with a maximum sample size of 100,000 users per group. You want to check the results at 25%, 50%, 75%, and 100% of the sample size. Using O'Brien-Fleming spending with α = 0.05, what are the critical z-values at each look?
Solution
Using the O'Brien-Fleming threshold formula z = z_{α/2} / √t with z_{α/2} = 1.96:
- Look 1 (t = 0.25): z = 1.96 / √0.25 = 1.96 / 0.5 = 3.92
- Look 2 (t = 0.50): z = 1.96 / √0.50 = 1.96 / 0.707 = 2.77
- Look 3 (t = 0.75): z = 1.96 / √0.75 = 1.96 / 0.866 = 2.26
- Look 4 (t = 1.00): z = 1.96 / √1.00 = 1.96 / 1.0 = 1.96
At the first look, you need a z-value of 3.92 (p < 0.0001) to stop. This is extremely conservative. At the final look, the threshold is the standard 1.96 (p < 0.05). You are running a 6-week experiment on a new feature. Traffic is limited — you can only reach 60% of the required sample size in 6 weeks. Stakeholders want to check results weekly. Should you use a fixed-sample or sequential design? Justify your choice.
Solution
You should use a sequential design. Here is the reasoning:
1. Stakeholders will peek regardless. If you use a fixed-sample design, stakeholders will check the dashboard weekly, and someone will stop the experiment early when p < 0.05. This inflates the false positive rate to 25-35%. A sequential design makes this peeking safe.
2. Traffic is limited. You cannot reach the full sample size in 6 weeks. A sequential design allows you to stop early if the effect is large, or to extend the experiment if the effect is small but promising.
3. The experiment is long (6 weeks). The ability to stop early saves significant time if the treatment has a large effect.
4. The sample size inflation for a sequential design with 6 looks is modest (approximately 5-8%). This is a small price for the flexibility and safety of sequential testing.
You should use O'Brien-Fleming spending with looks at weeks 1-6, and pre-specify both efficacy and futility boundaries. Quiz
1. Why does peeking at experiment results inflate the false positive rate?
2. What is the purpose of an alpha spending function in sequential testing?
3. What is the key advantage of e-values over group sequential designs?
Flashcards
Question
What is the peeking problem in A/B testing?
Click to reveal answer
Answer
Peeking is checking experiment results before the planned sample size is reached and stopping if the result is significant. It inflates the false positive rate because each peek is an additional opportunity to stop. With k peeks at α = 0.05, the false positive rate is approximately 1 - (1-α)^k. For 10 peeks, this is approximately 40% — eight times the nominal rate.
Question
How does alpha spending control the false positive rate in sequential tests?
Click to reveal answer
Answer
Alpha spending allocates the total alpha budget across multiple interim analyses. A spending function α*(t) determines how much alpha is used at each look, where t is the fraction of the sample size observed. The cumulative alpha across all looks never exceeds the nominal level (e.g., 0.05). O'Brien-Fleming spending is conservative early; Pocock spending allocates equal alpha at each look.
Question
What is an e-value and why is it useful for peeking?
Click to reveal answer
Answer
An e-value is a non-negative random variable whose expected value under the null is at most 1. E-values can be multiplied across time and the product remains valid. This means you can peek as often as you want and always have a valid test: if the product of e-values exceeds 1/α, you reject the null at level α. E-values provide always valid p-values without pre-specifying a peeking schedule.
Question
When should you use a sequential design instead of a fixed-sample design?
Click to reveal answer
Answer
Use a sequential design when: (1) the experiment is long and early stopping saves significant time, (2) stakeholders will peek regardless and you need to make peeking safe, (3) traffic is limited and you want to stop early if the effect is large, or (4) the treatment has potential for serious harm and you want to stop quickly. Use a fixed-sample design when you can enforce no-peeking and want maximum power.
Revision Notes
Key Takeaways
- 1. Peeking without a sequential procedure inflates the false positive rate from 5% to 25-50%
- 2. Alpha spending functions allocate the alpha budget across multiple looks while controlling the overall error rate
- 3. O'Brien-Fleming spending is conservative early, which prevents stopping based on noisy data
- 4. E-values provide always valid p-values that are correct regardless of how often you peek
- 5. Sequential designs require a modest sample size inflation (5-8% for 4-8 looks)
- 6. If stakeholders will peek regardless, use a sequential design to make peeking safe
Interview Tips
- • Be ready to explain why peeking inflates the false positive rate — each look is an additional test, and the p-value is a random walk that can cross the threshold multiple times
- • Discuss the tradeoff between fixed-sample and sequential designs — fixed-sample is more powerful but requires discipline, sequential is flexible but requires slightly more users
- • Explain e-values as a modern alternative to group sequential designs that provides validity under arbitrary peeking schedules
Cheat Sheet
Cheat Sheet: Sequential Testing and Peeking
The Peeking Problem
- Checking results before the planned sample size and stopping if significant
- Each peek is an additional false positive opportunity
- 10 peeks at α=0.05 → ~40% false positive rate
- Only safe if you use a sequential procedure
Alpha Spending
- Allocate α budget across multiple looks
- O'Brien-Fleming: conservative early, liberal late
- Pocock: equal alpha at each look
- Cumulative alpha never exceeds nominal level
O'Brien-Fleming Thresholds (α=0.05)
| Look | Fraction | z-threshold |
|---|---|---|
| 1 | 25% | 3.92 |
| 2 | 50% | 2.77 |
| 3 | 75% | 2.26 |
| 4 | 100% | 1.96 |
E-Values
- Non-negative random variable, E[E] ≤ 1 under null
- Multiply across time: product remains valid
- p_always_valid = min(1, 1/E)
- Valid regardless of peeking schedule
Design Choice
- Fixed-sample: enforce no-peeking, maximum power
- Sequential: flexible peeking, early stopping, modest sample inflation