A/B test design for LLM model selection in production

A/B TestingStatistical AnalysisLLM EvaluationPostHogMetabase

Context

We operate a conversational commerce platform where merchants use an LLM-powered assistant to engage customers and drive sales over messaging channels. The underlying model is a business-relevant lever: a better model can mean more conversions, but it also costs more per message. A new generation of our base model had just become available. On paper it promised stronger reasoning, but "on paper" doesn't pay the bills — before committing to a full migration we needed production evidence of the lift, across real merchants and real conversations.

Problem

A clean A/B on this looks simple until you look closer. Three things made it non-trivial:

  • Sparse, heterogeneous conversions: conversions per conversation are rare events, and the highest-volume merchants span different verticals, catalog types, and baseline conversion rates.
  • Analysis-unit trap: the natural assignment unit (session, reset after a window without customer reply) is not the natural analysis unit. Two sessions inside the same conversation aren't independent — analyzing at the session level would pseudo-replicate the data and inflate p-values.
  • Asymmetric rollout risk: shipping a worse model hurts revenue and merchant trust directly; shipping a better model late is recoverable. The test had to protect the downside.

Methodology

Experimental design:

  • Assignment: random 50/50 at conversation-session level via a feature flag, with the full cohort exposed to both variants.
  • Unit of analysis: conversation, not session, to avoid pseudo-replication. Conversations that saw both models (mixed) were excluded from analysis.
  • Metrics: a sale-mark event as the primary conversion metric (full coverage) and an order-level event as secondary (partial coverage). Average order value by currency as exploratory.
  • Statistics: two-proportion z-test for conversion, Mann-Whitney U for AOV (doesn't assume normality on amounts). Conventional significance threshold.
  • Window: multi-week production traffic.

Design validation

Before looking at results I verified the test had actually behaved as designed:

  • Sticky assignment: the vast majority of conversations stayed on a single model across all their sessions. The rest were excluded from analysis.
  • Balanced split: negligible deviation from 50/50 at the aggregate, and every individual merchant within the expected range. No drift.
  • Cumulative lift tracking: the lift became significant early in the window and stayed above threshold through the end. Robust result, not a lucky window.

Results

  • Double-digit aggregate conversion lift in favor of the candidate model, statistically significant. Similar magnitude on the secondary order-level metric.
  • Dramatically larger lift — several times the aggregate — concentrated in merchants using an integrated third-party catalog platform. For merchants on the native catalog, the lift was much smaller and not significant.
  • No meaningful change in average order value on any merchant/currency pair. The gain is in sales volume, not ticket size.
  • A couple of merchants showed a material negative lift: both on the native catalog, medium volume, with a high baseline conversion rate and heavily customized prompts.

Learnings

  • The average hid the real story: the aggregate lift was also a wide spread across merchants, from strongly positive to clearly negative. Segmentation by catalog source explained most of the variance — segmentation by country explained almost none.
  • Richer structured catalog data amplifies model capability. Likely mechanism: merchants on an integrated platform handle promotions as structured data; merchants on the native catalog embed promotion rules into free-text prompts, where a more capable model is more sensitive to inconsistency.
  • Session-level assignment is fine if you analyze at conversation level. The high sticky rate confirmed the two were near-equivalent in practice, but the methodology choice mattered for p-values — future experiments should move the flag granularity to conversation level.
  • Before scaling, cost is the gating decision. A given percentage lift is a different call at 1.5x, 3x, or 10x inference cost. Per-merchant cost tracking is the blocking analysis before any rollout.