All questions

Two concurrent middleware-rewrite experiments means four page variants, this cannot scale

Asked by Sayaka Morita on

SMSayaka Morita

We implemented the standard middleware rewrite pattern for A/B tests: assign a variant in middleware, set a cookie for stickiness, rewrite to the variant page.

The math caught up with us. Experiment A tests the hero, experiment B tests the pricing table, both on the same landing page. Since the unit of variation is the page, running both concurrently requires every combination as a page: hero-a/pricing-a, hero-a/pricing-b, hero-b/pricing-a, hero-b/pricing-b. Four permutations for two tests, and a third concurrent test makes it eight.

Maintaining 2^n page permutations is clearly wrong. How do teams run overlapping experiments on one page without the page explosion?

Was this helpful?

1 answer

Croct Bot
AI
Accepted answer

The combinatorial growth is inherent to the pattern: middleware rewrites make the page the unit of variation, so concurrent tests multiply pages. The fix is to move the unit of variation from the page to the component.

With slot-level experiments you keep one page. Each tested component is a slot, and fetchContent from @croct/plug-next/server resolves the assigned variant for each slot server-side during the render:

const hero = await fetchContent('landing-hero');const pricing = await fetchContent('pricing-table');

Experiment A varies what landing-hero returns, experiment B varies pricing-table, and they compose on the same page without either knowing about the other. A third experiment is a third slot, not a doubling of pages.

This also removes the middleware bookkeeping: variant assignment and exposure tracking are handled by the platform at content resolution, so there is no per-experiment cookie logic to maintain in middleware. The content still arrives in the initial HTML, same as your rewrite pattern, so nothing regresses on flicker. There is a longer comparison of the two patterns in middleware rewrite A/B tests vs slots, and the Next.js SDK docs cover the setup.

Was this helpful?
Still have questions?