01The scaling trap
Regression suites fail in a predictable way as teams grow. At five engineers, “run everything on every push” works — a 10-minute suite is invisible. At fifty engineers with a 90-minute E2E suite, the math stops working: ten concurrent PRs contend for runners, feedback latency kills flow state, and engineers start batching changes to “make CI worth it,” which multiplies both merge conflicts and risk.
The standard responses are both wrong. Cutting the suite (“we’ll rely on code review”) trades known costs for unknown ones — production incidents that a 30-second check would have caught. And brute-forcing with more machines hits an economic wall: E2E suites grow superlinearly in runtime because flows share setup and interact. The exit is not more hardware or fewer tests. It’s running the right tests, at the right time, with full knowledge of what changed.
02Risk-based selection starts from the diff
A pull request is a hypothesis about what it affects. Selection should encode exactly that hypothesis: map files to modules to user flows, then run the tests that exercise the touched surface plus everything downstream of it.
# .molar/policy.yaml - selection policy, versioned like code
rules:
- touch: "src/checkout/**"
run_flows: [cart, checkout, order-confirmation, refunds]
- touch: ["src/auth/**"]
run_flows: [signup, login, password-reset, session-security]
- touch: "package-lock.json"
run_flows: all # dependency bumps get everything
always_run: [smoke] # ~3 min, never skipped
The payoff is concrete: a PR that edits invoice rendering runs four flows (4 minutes) instead of sixty (55 minutes), while a dependency bump still gets the world. Keep the mapping in the repo, reviewed like code, because it is code — it encodes your beliefs about coupling, and stale mappings rot into silent gaps. This is also where AI-authored suites change the economics: when test generation is cheap, covering every affected flow stops being a headcount problem.
03Affected-flow analysis beats path matching
File-path rules are the floor, not the ceiling. A change to a shared component or an API response shape touches flows its path never mentions. The stronger version builds an actual dependency graph: which routes render this component, which flows traverse those routes, which API endpoints feed them.
$ molar affected --diff HEAD~3..HEAD
→ src/components/PricingTable.tsx changed
→ rendered on /pricing, /upgrade (2 routes)
→ traversed by flows: upgrade-plan, checkout (shared step: plan-select)
→ API deps: GET /api/plans (shape unchanged)
✓ Selected 7 specs, estimated 6m12s (full suite: 54m)
Two failure modes to design against. Over-selection (everything depends on everything) usually means a shared utility needs decoupling — treat it as architecture signal, not a tool bug. Under-selection is the dangerous one, and you catch it with data: when a nightly run finds a regression your selection missed, trace back which edge was absent from the graph and add it. Escape analysis feeds selection accuracy; see the measurement section below.
04The nightly full suite is insurance, not gating
Even good selection has blind spots: interactions between flows, environment drift, vendor behavior changes, cache poisoning that only manifests after hours of activity. The nightly full run exists to catch exactly those. Treat it as insurance — nobody waits on it to merge — but take its failures seriously: anything red at night that was green on merge is either a real cross-flow regression or a flaky test, and triage decides which within the morning.
- Schedule it off-peak against production-like data, using clones for third-party side effects so the run is safe to repeat (no dedicated staging needed).
- Capture evidence per flow — traces, network logs, DOM snapshots — so morning triage is reading, not re-running.
- Track suite duration weekly. A nightly that creeps from 40 to 90 minutes is telling you something about test debt before the PR gate feels it.
Production schedules extend the same idea outward: Guard-style recurring checks against live environments catch what no pre-merge suite can — CDN issues, cert expiry, vendor drift. That’s the complement to synthetic monitoring, not a replacement for the nightly.
05Quarantine and snooze: policy, not vibes
Flaky tests are where regression programs die. Not because flakes are unfixable — most have diagnosable causes (root causes and fixes here) — but because teams lack a shared policy, so every engineer improvises: mute it, delete it, retry-until-green, ignore red. Write the policy down instead:
- Quarantine means tracked. A quarantined test moves out of the gate, gets an owner and a ticket, and shows up on a dashboard. It does not vanish.
- Time-boxed hard. Fourteen days default. Quarantine without expiry is how suites rot while dashboards stay green.
- Snooze ≠ quarantine. Snoozing a known-flaky test during a feature branch is fine; quarantining a failing test to ship a release requires the owner’s name next to it.
- Budget the rate. If more than ~1–2% of the suite is quarantined at steady state, stop merging features and fix reliability — the gate’s credibility is the product.
06Measure escape rate, not vanity coverage
The only number that tells you whether any of this works is escape rate: regressions that reached users divided by total regressions found, over time. Everything else — coverage percent, test count, suite runtime — is an input metric that can look great while customers find bugs first.
escape_rate = bugs_found_in_production_with_regression_origin
/ (same_numerator + regressions_caught_by_suite)
# Track monthly, segment by area:
2026-03 18% (checkout 4, auth 2, billing UI 3)
2026-06 9% (checkout 1, auth 1)
# Every escape → write the missing test + trace why selection missed it
Pair it with two operational metrics: time-to-feedback on the PR gate (target: under ten minutes, or developers context-switch) and detection latency for production issues (how long between a synthetic check failing and a human acting). Escapes going down while feedback stays fast is the whole game. When escapes cluster in one area, that’s your selection graph missing edges — fix the mapping, then let the self-healing layer absorb the locator churn those new tests will hit.
Finally, make the gate itself non-negotiable: required status checks turn “please run the tests” into physics. The mechanics are in our guide to required checks as a merge gate.
A regression system that scales with your team
Molar maps your app’s flows once, selects the right tests per PR, runs nightly insurance with full evidence, and monitors production on schedules — so speed and safety stop trading off.