Use case · E-commerce

Find the discount that pays for itself

Your discount is a constant in the codebase. Changing it is a deploy, and after margin nobody can say whether 15% actually earns more than 10%.

3 parameters, one changemargin as a blocking guardrail

The problem

Your discount is a constant in the codebase.

Every pricing conversation ends the same way: someone proposes a deeper discount, someone else says it will destroy margin, and there is no evidence either way. So the number stays where it is — usually because a founder picked it three years ago.

When teams do change it, they change it for everyone at once, on a Tuesday, and read revenue in aggregate. Seasonality moves more than the discount did, so the readout proves nothing and the argument repeats next quarter.

The failure is not the pricing intuition. It is that a discount touches checkout, the mobile app, the pricing service and the win-back email, and the only way to move it safely was to move all four together and hope.

the usual state of things
# four places, one number
storefront/checkout.ts:   DISCOUNT = 10
mobile/Cart.swift:        discount = 10
pricing-svc/rules.py:     DISCOUNT_PCT = 10
crm/templates/winback:    "Save 10%"

# changing it: 4 PRs, 4 deploys,
# and a window where they disagree

What you put under control

Declared once, then governed centrally. This is the only code step.

Parameters
ParameterTypeDefaultRange
pricing.discount_pctnumber100–50
pricing.free_shippingbooleanfalse
pricing.free_ship_thresholdnumber7500cents
Surfaces that consume them
SurfaceKindRole
Checkoutfrontendrender
Mobile appfrontendrender
Pricing servicebackenddecision
Win-back emailemailrender

Those bindings are what compute the risk class — medium: backend surface · decision binding.

Variants are parameter value sets
Variantdiscount_pctfree_shipping
control10false
deeper15false
bundled10true

Risk class: medium

backend surface · decision binding. A human approves the measurement plan before any traffic, and again before the value becomes the product default.

How it runs

The mechanism is configuration. The application code is already done.

Canary → Experiment → Rollout
Chosen for a medium-risk change.

Pricing is a decision binding on a backend surface, so the computed risk is medium and the canary comes first. Once the experiment picks a winner, the rollout ramps it in health-gated steps.

Later, an adaptive policy can keep tuning the winning value per segment — same parameter, no code change.

Phases live
Setup
Canary
Experiment
Rollout
Complete
Guardrails on every phase
margin
must not decrease > 2%
blocking
refund_rate
must not increase > 0.5%
blocking
checkout_error_rate
must not increase > 1%
warning

What you get back

A verdict you can defend, and the reasoning kept for next time.

checkout-pricing / measurement live
Evidence still accumulating — hold
Leading variant is ahead on the primary metric, but the interval has not cleared zero. All guardrails passing.
primary metric
+4.2%
revenue_per_session · ratio · sum(revenue) / sessions
measurement progress
64%
of the sample needed for a verdict
guardrails
3 / 3
passing, none near threshold
revenue_per_session primary
deeper +4.2% · anytime-valid interval still crosses zero
+4.2%
margin guardrail
inside the acceptable band on all arms
passing
refund_rate guardrail
inside the acceptable band on all arms
passing

A discount level you can defend in a board meeting — and a margin guardrail that pauses the phase before anyone notices.

When it completes, the winning values become the parameter defaults and the whole thing — question, variants, evidence, verdict — is retained. The next person to propose moving this number starts from the answer instead of the argument.

Retained after this change

The question asked, the values tried, the interval at the moment of the call, which thresholds were in force, and who approved the promotion.

Searchable by parameter, surface, or metric

Keep reading

The mechanics behind this page.

Start with this one number

Parameterize it this week. The first measured change usually pays for the integration.