A/B Test Design
When to use this skill
Use when the user is planning an experiment, not analyzing one. Triggers include:
- "Design an A/B test for…"
- "What sample size do I need…"
- "How long should I run this test…"
- "Pre-register this experiment"
- "Pick guardrails for…"
If the user already has results, use ab-test-analysis instead.
Required inputs
Collect these before computing anything. If missing, ask.
| Input |
Why it matters |
| Primary metric |
Determines test type (proportion, mean, ratio) |
| Baseline rate or mean |
Required for power calculation |
| Minimum detectable effect (MDE) |
Sets sensitivity floor |
| Randomization unit |
User, session, account, device |
| Expected daily exposure (units/day) |
Determines runtime |
| Variant count (control + N treatments) |
Affects multiple-comparison correction |
| Guardrail metrics |
What must not regress |
Workflow
Confirm hypothesis is testable. A hypothesis has the form: "Changing X will move metric Y by at least Z%, because reason R." If reason R is missing, push back.
Pick the metric type.
- Binary outcome (conversion, click) -> proportion test
- Continuous (revenue per user, session length) -> mean test, log-transform if skewed
- Ratio (revenue per impression) -> delta method or bootstrap
Set MDE conservatively. Default to the smallest effect the team would actually act on. Do not optimize MDE to fit the runtime — that's how teams ship noise.
Compute sample size using scripts/sample_size.py. Default to alpha=0.05, power=0.80, two-sided.
Compute runtime = (sample size per arm × num arms) / daily exposure. Round up to a full business cycle (e.g., 14 days minimum to capture weekday/weekend variance).
Define guardrails. Minimum three:
- One business guardrail (e.g., revenue/user must not drop > X%)
- One quality guardrail (e.g., error rate, latency)
- One reach guardrail (assignment ratio sanity check, sample ratio mismatch)
Write pre-registration doc using the template below.
Output format
Produce a pre-registration block:
# Experiment Pre-Registration: <name>
## Hypothesis
Changing <X> will move <Y> by at least <Z>%, because <R>.
## Variants
- Control: <description>
- Treatment 1: <description>
- (Treatment 2: <description>)
## Randomization
- Unit: <user | session | account>
- Allocation: <e.g., 50/50, 33/33/33>
## Metrics
- Primary: <metric name, definition, source table>
- Secondary: <list>
- Guardrails: <list with thresholds>
## Power
- Baseline: <value>
- MDE: <value> (absolute / relative)
- Alpha: 0.05
- Power: 0.80
- Required sample per arm: <N>
- Expected daily exposure per arm: <N/day>
- Minimum runtime: <D days> (≥ 14 days to cover one weekly cycle)
## Stopping rules
- No peeking before <date>
- Stop early only on guardrail breach (specify threshold)
## Analysis plan
- Test: <z-test / t-test / Mann-Whitney / CUPED-adjusted>
- Subgroup analyses (pre-specified): <list or "none">
Validation checks
Before finalizing, verify:
Edge cases & failure modes
- Network effects (marketplaces, social): user-level randomization leaks treatment. Use cluster randomization (geo, cohort) or switchback designs.
- Very rare events (< 1% base rate): sample size explodes. Consider proxy metrics or longer runtime.
- Long conversion windows: define the observation window explicitly. A "7-day conversion" experiment running 7 days has no fully-observed users yet.
- Novelty / primacy effects: plan a 14-day minimum and discard the first 2-3 days from analysis if needed (pre-specify this).
Scripts
scripts/sample_size.py — Sample size calculator for proportion and mean tests.
python scripts/sample_size.py --metric-type proportion --baseline 0.12 --mde 0.01 --alpha 0.05 --power 0.80
python scripts/sample_size.py --metric-type mean --baseline-mean 45.2 --baseline-std 18.4 --mde 2.0
Related skills
ab-test-analysis — read out results after the experiment runs
metric-definition — write precise specs for primary and guardrail metrics
causal-inference — for situations where RCT isn't feasible
1---2name: ab-test-design3description: Designs A/B tests with power analysis, minimum detectable effect (MDE), sample size estimation, randomization unit selection, guardrail definition, and a pre-registration checklist. Use when the user mentions experiment design, A/B test setup, power analysis, sample size, MDE, pre-registration, randomization, or asks "how should I run this experiment."4---56# A/B Test Design78## When to use this skill910Use when the user is **planning** an experiment, not analyzing one. Triggers include:1112- "Design an A/B test for…"13- "What sample size do I need…"14- "How long should I run this test…"15- "Pre-register this experiment"16- "Pick guardrails for…"1718If the user already has results, use `ab-test-analysis` instead.1920## Required inputs2122Collect these before computing anything. If missing, ask.2324| Input | Why it matters |25|---|---|26| Primary metric | Determines test type (proportion, mean, ratio) |27| Baseline rate or mean | Required for power calculation |28| Minimum detectable effect (MDE) | Sets sensitivity floor |29| Randomization unit | User, session, account, device |30| Expected daily exposure (units/day) | Determines runtime |31| Variant count (control + N treatments) | Affects multiple-comparison correction |32| Guardrail metrics | What must not regress |3334## Workflow35361. **Confirm hypothesis is testable.** A hypothesis has the form: "Changing X will move metric Y by at least Z%, because reason R." If reason R is missing, push back.37382. **Pick the metric type.**39 - Binary outcome (conversion, click) -> proportion test40 - Continuous (revenue per user, session length) -> mean test, log-transform if skewed41 - Ratio (revenue per impression) -> delta method or bootstrap42433. **Set MDE conservatively.** Default to the smallest effect the team would actually act on. Do not optimize MDE to fit the runtime — that's how teams ship noise.44454. **Compute sample size** using `scripts/sample_size.py`. Default to alpha=0.05, power=0.80, two-sided.46475. **Compute runtime** = (sample size per arm × num arms) / daily exposure. Round up to a full business cycle (e.g., 14 days minimum to capture weekday/weekend variance).48496. **Define guardrails.** Minimum three:50 - One business guardrail (e.g., revenue/user must not drop > X%)51 - One quality guardrail (e.g., error rate, latency)52 - One reach guardrail (assignment ratio sanity check, sample ratio mismatch)53547. **Write pre-registration doc** using the template below.5556## Output format5758Produce a pre-registration block:5960```markdown61# Experiment Pre-Registration: <name>6263## Hypothesis64Changing <X> will move <Y> by at least <Z>%, because <R>.6566## Variants67- Control: <description>68- Treatment 1: <description>69- (Treatment 2: <description>)7071## Randomization72- Unit: <user | session | account>73- Allocation: <e.g., 50/50, 33/33/33>7475## Metrics76- Primary: <metric name, definition, source table>77- Secondary: <list>78- Guardrails: <list with thresholds>7980## Power81- Baseline: <value>82- MDE: <value> (absolute / relative)83- Alpha: 0.0584- Power: 0.8085- Required sample per arm: <N>86- Expected daily exposure per arm: <N/day>87- Minimum runtime: <D days> (≥ 14 days to cover one weekly cycle)8889## Stopping rules90- No peeking before <date>91- Stop early only on guardrail breach (specify threshold)9293## Analysis plan94- Test: <z-test / t-test / Mann-Whitney / CUPED-adjusted>95- Subgroup analyses (pre-specified): <list or "none">96```9798## Validation checks99100Before finalizing, verify:101102- [ ] Primary metric has a single, unambiguous SQL definition103- [ ] Randomization unit matches the unit at which the treatment is delivered104- [ ] Runtime covers at least one full weekly cycle105- [ ] Sample ratio mismatch (SRM) check is part of the analysis plan106- [ ] Guardrails have explicit thresholds and stop-the-experiment rules107- [ ] No more than 1 primary metric (multiple primaries inflate false positives)108109## Edge cases & failure modes110111- **Network effects** (marketplaces, social): user-level randomization leaks treatment. Use cluster randomization (geo, cohort) or switchback designs.112- **Very rare events** (< 1% base rate): sample size explodes. Consider proxy metrics or longer runtime.113- **Long conversion windows**: define the observation window explicitly. A "7-day conversion" experiment running 7 days has no fully-observed users yet.114- **Novelty / primacy effects**: plan a 14-day minimum and discard the first 2-3 days from analysis if needed (pre-specify this).115116## Scripts117118- `scripts/sample_size.py` — Sample size calculator for proportion and mean tests.119120```bash121python scripts/sample_size.py --metric-type proportion --baseline 0.12 --mde 0.01 --alpha 0.05 --power 0.80122python scripts/sample_size.py --metric-type mean --baseline-mean 45.2 --baseline-std 18.4 --mde 2.0123```124125## Related skills126127- `ab-test-analysis` — read out results after the experiment runs128- `metric-definition` — write precise specs for primary and guardrail metrics129- `causal-inference` — for situations where RCT isn't feasible