Pricing Strategy and Business Model Questions
Setting and evolving prices and the monetization model they sit in. Covers pricing metrics and structure (per-seat, tiered, usage-based, hybrid, outcome-based), packaging and bundling, freemium versus paid versus ad-supported monetization, and migrating between pricing models, including from perpetual licences to subscription and consumption billing. Includes estimating willingness to pay and price elasticity (van Westendorp, Gabor-Granger, conjoint, observational and causal methods), designing and analysing price tests and reporting their results, discount and deal-desk policy, regional and personalized pricing, and quantifying the revenue, churn, LTV and margin impact of a price or packaging change. Also covers fee design and surge pricing on two-sided marketplaces, responding to competitor price cuts, and rolling out algorithmic pricing safely. Assesses commercial judgment and quantitative rigor on pricing decisions from product, sales, finance and analytics angles. Business-model archetype selection, unit-economics definitions and go-to-market execution are adjacent topics, not the focus.
Design a dashboard that presents pricing experiment results to executives and the sales team. What would you show, how would you convey uncertainty, and how would the views differ for each audience?
Sample Answer
Direct answer
Build one dashboard with two views on the same numbers. The executive view answers "should we ship, wait or stop" with one decision card, an interval and a pre-agreed threshold. The sales view answers "what does this mean in my deals" with counts, segment cuts labelled as exploratory (patterns found by slicing the data, to be treated as hypotheses, not results), and no live significance flags that invite early conclusions.
Shared foundation (both views)
- Test health banner: sample ratio check (does the split of accounts between arms match the planned split; a mismatch means assignment is broken), data freshness and days remaining.
- One metric dictionary: each metric has a one-line definition on hover.
- Variant definitions: price points and what each plan includes.
Executive view (illustrative excerpt)
The 95% interval is the range of differences the data are consistent with; if the experiment were repeated many times, about 95% of such intervals would contain the true difference. Guardrail metrics are safety checks that must not get worse while the main metric improves.
Decision card:
Usage-based vs flat, gross margin per new account, first 90 days
Flat (control): $400. Usage-based: $424.
Difference: +$24 (+6.0%). 95% interval: -$4 to +$52 (-1.0% to +13.0%).
Ship threshold agreed before launch: at least +3%. Status: not yet conclusive; the interval includes both a small loss and a gain above the threshold. Next read in 2 weeks, when the sample reaches the planned size.
Below it, in this order:
- Interval chart: a horizontal bar for the difference with the zero line and the +3% threshold marked, so the reader sees the range against the bar for a decision. A sketch drawn to scale with the card's numbers (the threshold of 3% of $400 is +$12; the estimate sits at the middle of the interval, $24 between -$4 and +$52):
-$4 0 +$12 +$24 +$52
[----|-----------|-----------o----------------------------]
| = zero line and threshold (+$12), o = estimate (+$24); drawn to scale, one character is $1
- Guardrail tiles: one tile per guardrail metric (a metric that must not get worse), such as retention, bill-shock tickets and largest invoices. Green or amber is judged against limits set in advance.
- Time series of the difference with its interval, annotated with changes made during the test, and a note that day-to-day wiggles before the planned sample size are not decisions.
- Recommendation line in plain language: ship, wait, stop, with what would change it.
Sales view
| Element | Why |
|---|---|
| Deals and win rate (share of deals that close as won) by arm, with counts | Shows what the field experiences; counts stop over-reading small samples |
| Discount requested and granted, by arm | Shows whether usage pricing creates negotiating pressure |
| Typical bill for a customer of each size under each plan | Lets reps explain the plan to a buyer |
| Deal-cycle length and objections tagged by pricing | Qualitative signal that revenue metrics miss |
| Segment cuts (size, region), labelled "exploratory" | Sellers will ask; showing them with wide intervals is safer than refusing |
How uncertainty is conveyed
- Always show an interval next to a point estimate, and the decision threshold next to the interval.
- Use plain language: "the data are consistent with anything from a $4 loss to a $52 gain per account", not "p = 0.09" (the chance of a gap at least this large if the plans were truly equal is 9%).
- Show sample size against planned size, so readers know how much more evidence is coming.
- Do not display a running "significant" flag (one that switches on when the p-value drops below 0.05). Peeking, which is checking daily and stopping the first time it looks significant, gives noise many chances to cross the line, so false wins become likely. Show the result only at planned checkpoints, or use a sequential testing method, which is designed for continuous monitoring by widening the interval to account for repeated looks.
- For small segments show counts and wide intervals instead of hiding them.
How the views differ
| Executives | Sales | |
|---|---|---|
| Question | Ship, wait or stop? | What does it mean for my deal? |
| Lead with | Decision card and interval | Deal counts and typical bills |
| Detail | Guardrails and time series | Segments, objections, discounts |
| Language | Margin per account, retention | Win rate, discount, price per customer size |
Trade-offs and pitfalls
- Too many segment cuts produce false positives: with 20 cuts at a 5% false-alarm rate each, you expect 20 x 5% = 1 to look significant by chance. Label them exploratory and check them in a follow-up.
- A single revenue number hides margin: show gross margin, or the winner may be the plan that attracts expensive users.
- What would change my call: if the audience is unfamiliar with intervals, I would keep the interval but pair it with the plain-language sentence, not drop it.
A product charges $100 a month, has 1,000 customers and 5% monthly churn. You are considering a 10% price increase. Build a simple model: what happens to revenue next month, and what is the 12-month view if churn rises?
Sample Answer
Direct answer
Raising the price from $100 to $110 with churn unchanged at 5% gives next month's revenue of $104,500 versus $95,000 baseline (+10%): customers retained after the 5% churn (950) times the new price. Over 12 months the price rise is worth about +$87,332 if churn stays at 5%, but if churn rises permanently to about 6.55% a month the extra revenue vanishes; at 7% it loses $23,636, and at 8% it loses $73,414.
Definitions and set-up
- Churn: the share of customers who cancel each month (5% here). This is logo churn: it counts customers lost, not revenue lost.
- Revenue in a month = customers still paying x price. Timing assumed: churn happens at renewal, and survivors are billed the new price.
- Baseline month 1: 1,000 x (1 - 0.05) = 950 customers x $100 = $95,000.
- New price, same churn: 950 x $110 = $104,500.
- One-month break-even churn: the churn at which revenue falls back to $95,000: customers x (1 - c) x $110 = $95,000, so 1 - c = 95,000 / 110,000 = 0.8636 and c = 13.64%. A single month tolerates a lot of extra churn, which is why one-month views flatter price rises.
Build the model
PRICE_OLD, PRICE_NEW, CUSTOMERS = 100, 110, 1_000 # $ per customer per month
def twelve_months(price, monthly_churn):
"""monthly_churn: list of monthly rates (any length). Churn happens at renewal, then the survivors pay."""
customers, total, first, last = CUSTOMERS, 0.0, None, None
for churn in monthly_churn:
customers *= (1 - churn)
revenue = customers * price
total += revenue
first = revenue if first is None else first
last = revenue
return total, first, last, customers
base_total = twelve_months(PRICE_OLD, [0.05] * 12)[0]
print("baseline: total=%.0f" % base_total)
cases = {
"price up, churn stays 5%": [0.05] * 12,
"price up, churn 6% every month": [0.06] * 12,
"price up, churn 7% every month": [0.07] * 12,
"price up, churn 8% every month": [0.08] * 12,
"price up, 10% in month 1 then 5%": [0.10] + [0.05] * 11,
}
for name, churns in cases.items():
total, first, last, end = twelve_months(PRICE_NEW, churns)
print("%-34s month1=%6.0f month12=%6.0f customers_end=%5.1f total=%7.0f vs baseline %+.0f"
% (name, first, last, end, total, total - base_total))
# Break-even search: try a permanent churn rate, check whether the price rise still beats the baseline,
# and keep narrowing between "still beats it" (lo) and "no longer beats it" (hi).
def break_even_churn(months):
base = twelve_months(PRICE_OLD, [0.05] * months)[0]
lo, hi = 0.05, 0.20
for _ in range(60):
mid = (lo + hi) / 2
if twelve_months(PRICE_NEW, [mid] * months)[0] > base: lo = mid
else: hi = mid
return lo
print("12-month break-even permanent churn: %.2f%%" % (break_even_churn(12) * 100))
print("24-month break-even permanent churn: %.2f%%" % (break_even_churn(24) * 100))
print("1-month break-even churn: %.2f%%" % ((1 - 95_000 / (CUSTOMERS * PRICE_NEW)) * 100))
# Lifetime value (LTV) per customer = monthly revenue (or margin) / monthly churn
# Cost to serve is an illustrative $20 per customer per month.
for basis, cost in (("revenue basis", 0), ("margin basis ", 20)):
old = (PRICE_OLD - cost) / 0.05
new = (PRICE_NEW - cost) / 0.06
print("%s: LTV old=%.1f new=%.1f new per trial (-5%% conversion)=%.1f" % (basis, old, new, new * 0.95))
print("churn at which LTV is unchanged: revenue basis %.2f%%, margin basis %.3f%%"
% (PRICE_NEW / (PRICE_OLD / 0.05) * 100, (PRICE_NEW - 20) / ((PRICE_OLD - 20) / 0.05) * 100))
Output:
baseline: total=873316
price up, churn stays 5% month1=104500 month12= 59440 customers_end=540.4 total= 960647 vs baseline +87332
price up, churn 6% every month month1=103400 month12= 52351 customers_end=475.9 total= 903164 vs baseline +29848
price up, churn 7% every month month1=102300 month12= 46046 customers_end=418.6 total= 849680 vs baseline -23636
price up, churn 8% every month month1=101200 month12= 40443 customers_end=367.7 total= 799902 vs baseline -73414
price up, 10% in month 1 then 5% month1= 99000 month12= 56311 customers_end=511.9 total= 910087 vs baseline +36771
12-month break-even permanent churn: 6.55%
24-month break-even permanent churn: 5.91%
1-month break-even churn: 13.64%
revenue basis: LTV old=2000.0 new=1833.3 new per trial (-5% conversion)=1741.7
margin basis : LTV old=1600.0 new=1500.0 new per trial (-5% conversion)=1425.0
churn at which LTV is unchanged: revenue basis 5.50%, margin basis 5.625%
Reading the 12-month view
| Scenario | 12-month revenue | Versus baseline ($873,316) |
|---|---|---|
| Price up, churn stays 5% | $960,647 | +$87,332 |
| Churn 6% each month | $903,164 | +$29,848 |
| Churn 7% each month | $849,680 | -$23,636 |
| Churn 8% each month | $799,902 | -$73,414 |
| Churn 10% in month 1, then 5% | $910,087 | +$36,771 |
At 7% permanent churn the business also ends month 12 with 418.6 customers versus 540.4 in the baseline, a smaller base that costs future months too. So the 12-month break-even of 6.55% is not a permanent safe zone: over 24 months the same calculation gives 5.91%, because lost customers keep not paying. A hand check of the 24-month figure: with a permanent churn rate c, revenue over n months is price x 1,000 x (1 - c) x (1 - (1 - c)^n) / c. For the $100 baseline at 5% over 24 months, that is 100 x 1,000 x 0.95 x (1 - 0.2920) / 0.05 = about $1,345,200. For $110 at 5.91% it is 110 x 1,000 x 0.9409 x (1 - 0.2317) / 0.0591 = about $1,345,400, the same, so 5.91% is the break-even.
The search loop in the code does the same thing by trial: it guesses a permanent churn rate, checks whether the $110 plan still beats the $100 baseline over the chosen number of months, and keeps narrowing between a rate where it still wins and a rate where it loses.
The one-time spike scenario shows that a short, one-off churn bump is survivable, but a persistent rise is not.
Lifetime value view (same $100 to $110 price, churn 5% to 6%)
LTV (lifetime value) is what one customer is worth before cancelling: monthly revenue per customer divided by monthly churn, because the expected lifetime is 1 / churn months. At 5% churn a customer stays 20 months on average.
- Revenue basis: old $100 / 0.05 = $2,000. New $110 / 0.06 = $1,833. Price rose 10% but churn rose 20% (0.06 / 0.05 = 1.2), so lifetime revenue per customer falls about 8%. LTV would be unchanged only if churn rose to 5.5% (110 / 2,000).
- Trial conversion down 5% (taken as 5% relative, for example 4.00% becoming 3.80%; if it means 5 percentage points the drop is larger). Trial conversion is the share of free-trial users who become paying customers. LTV per trial started = 1,833 x 0.95 = $1,742 against $2,000.
- Margin basis. Margin is revenue minus cost to serve (the cost of delivering the product to one customer for a month), here an illustrative $20, so margin per month is $80 old and $90 new. Old 80 / 0.05 = $1,600; new 90 / 0.06 = $1,500; per trial 1,500 x 0.95 = $1,425. On margin the break-even churn is 90 / 1,600 = 5.625%: the extra $10 of price is all margin, so the margin basis tolerates slightly more churn than the revenue basis, but a one-point rise is still too much.
The conclusion is the same on both bases: with churn up a full point, the price rise improves the next month's revenue but lowers lifetime value.
Sensitivity and pitfalls
- The most sensitive assumption is how much churn rises, which the price rise itself determines. Estimate it from a test or from past price changes, not by assumption.
- Stay on one basis: monthly churn and monthly price, customers (not revenue) churn.
- Real changes also move who churns: price-sensitive customers leave first, so the remaining base may be less price-sensitive, and an increase on the existing base differs from one for new customers only.
- Do not ignore the revenue-quality side: a higher price with higher churn adds support cost for replacing customers.
A product is moving from flat monthly billing to consumption-based pricing. How would you forecast the distribution of usage per customer, estimate revenue under tiered consumption rates, and model the impact on invoicing timing and revenue predictability?
Sample Answer
Direct answer
I would fit a distribution to each customer's metered usage history, apply the tier rates to simulated bills to get revenue and the spread of invoices, then model invoicing timing separately, because usage billed in arrears (after the usage has happened) pulls cash later than flat billing in advance. Predictability needs two views: the total, which is stable, and the individual customer's bill, which is not.
Steps
- Get usage under the old plan. Flat billing may not meter usage, so check whether the data exists, is complete and has the same unit as the new pricing.
- Describe the distribution. Usage per customer is typically right-skewed (a long tail on the high side: many small users, a few very large). Summarise by median, p90 (90th percentile: 90% of customer-months use less) and p99 (99% use less), and use a log scale. A lognormal distribution (logarithm of usage is bell-shaped) is a reasonable starting model; check the fit against the real histogram.
- Separate customer size from month-to-month noise. Each customer has a typical volume and fluctuates around it; the aggregate and the individual bill behave differently. In practice, give each customer one typical-volume draw held fixed for the year and a fresh noise draw each month, and multiply them. The noise averages out across 1,000 customers but not within one customer.
- Apply the tier rates. Compute each customer's bill with marginal tiers (each unit is priced by the tier it falls into).
- Add a behaviour scenario. Customers who pay per unit often use less. Treat the size as a scenario, not an estimate, until a pilot measures it.
- Model invoicing timing. Flat fee billed at the start of the month; usage billed after the month closes, with payment terms on top.
- Report winners and losers. The share of customers who pay more than today drives churn and support load.
Worked example
Illustrative data: 1,000 customers, 12 months, typical volume lognormal around 2,000 units a month with log standard deviation 1.0, monthly noise with log standard deviation 0.3 (independent across customers, which understates correlated swings in real life). Current flat fee $250 per customer per month. Tiers: first 1,000 units at $0.12, next 4,000 at $0.07, above 5,000 at $0.035 per unit. Log standard deviation 1.0 means a customer one standard deviation above the median uses about e (2.7) times as much: 2,000 x 2.7, about 5,400 units. Hand-check of one bill: 2,000 units cost 1,000 x $0.12 + 1,000 x $0.07 = $120 + $70 = $190; 6,000 units cost $120 + 4,000 x $0.07 + 1,000 x $0.035 = $120 + $280 + $35 = $435.
The script draws a typical volume for each of 1,000 customers, multiplies by monthly noise to make 12,000 customer-months of usage, prices each month with the tier function, and then prints revenue by month, the share of customers who would pay more than $250, and how often a bill moves more than 25% from the previous month. The noise term subtracts half the variance (mean=-0.5 x 0.3 squared) so the average noise multiplier is exactly 1.0: it reshuffles months without raising or lowering total usage.
import numpy as np
rng = np.random.default_rng(42)
N, MONTHS = 1_000, 12
FLAT = 250.0 # current flat fee, $ per customer per month
# Illustrative history: each customer has a typical monthly volume (units) plus month-to-month noise
typical = rng.lognormal(mean=np.log(2_000), sigma=1.0, size=N)
noise = rng.lognormal(mean=-0.5 * 0.3**2, sigma=0.3, size=(N, MONTHS))
usage = typical[:, None] * noise
def tiered_bill(units):
# first 1,000 units at $0.12, next 4,000 at $0.07, everything above 5,000 at $0.035
return (np.minimum(units, 1_000) * 0.12
+ np.clip(units - 1_000, 0, 4_000) * 0.07
+ np.maximum(units - 5_000, 0) * 0.035)
bill = tiered_bill(usage)
total = bill.sum(axis=0) # revenue per month across all customers
print("Units per customer-month: median %.0f, mean %.0f, p90 %.0f, p99 %.0f" % (
np.median(usage), usage.mean(), np.percentile(usage, 90), np.percentile(usage, 99)))
print("Flat revenue per month: $%.0f" % (FLAT * N))
print("Tiered revenue per month: mean $%.0f, min $%.0f, max $%.0f" % (total.mean(), total.min(), total.max()))
print("Month-to-month variation of total tiered revenue (std/mean): %.1f%%" % (100 * total.std() / total.mean()))
print("Customers whose average bill exceeds the flat fee: %.0f%%" % (100 * (bill.mean(axis=1) > FLAT).mean()))
avg = bill.mean(axis=1)
print("Median customer average bill: $%.0f" % np.median(avg))
top = np.sort(avg)[::-1]
print("Top 10%% of customers' share of revenue: %.0f%%" % (100 * top[: N // 10].sum() / top.sum()))
change = np.abs(bill[:, 1:] / bill[:, :-1] - 1)
print("Share of customer-months where the bill moves more than 25%% vs last month: %.0f%%" % (100 * (change > 0.25).mean()))
# Behaviour response: customers now pay per unit, so assume usage falls 10% (a scenario, not a measurement)
print("Tiered revenue per month if usage falls 10%%: $%.0f" % tiered_bill(usage * 0.9).sum(axis=0).mean())
Output:
Units per customer-month: median 1876, mean 3142, p90 6990, p99 20166
Flat revenue per month: $250000
Tiered revenue per month: mean $235587, min $231284, max $238650
Month-to-month variation of total tiered revenue (std/mean): 1.0%
Customers whose average bill exceeds the flat fee: 35%
Median customer average bill: $186
Top 10% of customers' share of revenue: 28%
Share of customer-months where the bill moves more than 25% vs last month: 44%
Tiered revenue per month if usage falls 10%: $218241
Reading the output:
- Revenue: tiered revenue averages about $235,600 a month against $250,000 flat, roughly 6% lower. If usage falls 10% in response, about $218,200: the price response matters more than the tier detail.
- Winners and losers: 35% of customers would pay more than $250; the median customer pays about $186 a month. The people who pay more are the heavy users, who may also be the most valuable.
- Predictability: total revenue varies by only 1.0% month to month, but 44% of customer-months move by more than 25% against the previous month. A finance team sees a stable total while individual customers see unstable invoices. The 1.0% is optimistic: it assumes noise is independent across customers, so a shared event (a seasonal peak, an outage) would make the total move far more.
- Concentration: the top 10% of customers produce about 28% of revenue, so the forecast error is driven by a few accounts; forecast those individually.
Invoicing timing
Flat billing in advance collects about $250,000 on day one of each month. Usage billing is known only after month end, then invoiced and paid on terms, so the first usage cash arrives roughly one to two months after switching. At about $235,600 a month of revenue, that is a one-time working-capital gap (cash the business must fund while waiting to be paid) of the order of one to two months of revenue, roughly $236,000 to $471,000 in this example. Mitigate with a commitment (a minimum monthly charge), billing in advance for a prepaid usage balance, or mid-month interim invoices.
Trade-offs and pitfalls
- Aggregate predictability is not customer predictability; bill shock drives churn even when the total is steady.
- Never fit usage only on active customers: customers who left or were capped under the flat plan are missing.
- Do not reuse the historical distribution unchanged: behaviour will shift once usage costs money.
- What I would check first: whether the tier boundaries sit near the median, since many customers just above a boundary produce the largest bill changes.
You are evaluating per-user pricing ($10/user/mo) versus a flat-fee $500/mo for teams. How would you model revenue and customer value across segments (small teams vs large orgs), calculate break-even team size for flat-fee, and discuss churn sensitivity and sales implications for each model?
Sample Answer
Direct answer
The break-even team size (the size at which the two prices are equal) is 50 seats: $500 / $10 per seat per month. Below 50 seats per-user pricing is cheaper for the customer, above it the flat fee is. Which model earns more depends less on that threshold than on who buys under each model, so I would model revenue by segment with an explicit assumption for how many small teams still buy at $500, and I would lean towards per-user pricing with seat bands (a lower price per seat for the seats beyond certain team sizes) rather than a hard $500 cap, because it keeps expansion revenue and does not price small teams out. A hard $500 cap earns the least of the options modelled below ($140,000 a month), so the bands are the way to give big accounts a better price without freezing their growth.
Customer view: price per team by size
| Seats | Per-user ($10/seat/mo) | Flat ($/mo) | Effective flat price per seat |
|---|---|---|---|
| 5 | $50 | $500 | $100.00 |
| 10 | $100 | $500 | $50.00 |
| 25 | $250 | $500 | $20.00 |
| 50 | $500 | $500 | $10.00 (break-even) |
| 100 | $1,000 | $500 | $5.00 |
| 300 | $3,000 | $500 | $1.67 |
All figures are dollars per team per month, so both models share a basis. Break-even in algebra: 10 x N = 500, so N = 50.
Revenue model by segment (illustrative mix)
Assume 1,000 teams: 600 teams of 5 seats, 300 of 20, 80 of 60 and 20 of 300. Assume everyone buys under per-user pricing. Under the flat fee assume only some buy: 25% of 5-seat teams (the price is 10x what they pay today), 70% of 20-seat teams, and all teams of 60 and 300 (they get a discount). The buy rates are guesses; the interesting output is how far they can move.
PER_SEAT, FLAT = 10, 500 # dollars per month
mix = [(5, 600), (20, 300), (60, 80), (300, 20)] # (seats per team, number of teams)
flat_buy = {5: 0.25, 20: 0.70, 60: 1.0, 300: 1.0} # share of each size that buys at the flat fee
per_user = sum(seats * PER_SEAT * teams for seats, teams in mix)
flat = sum(teams * flat_buy[seats] * FLAT for seats, teams in mix)
capped = sum(min(seats * PER_SEAT, FLAT) * teams for seats, teams in mix)
def banded(seats):
"""Seat bands: $10 a seat up to 50 seats, $7 a seat for seats 51-200, $5 a seat above 200."""
return min(seats, 50) * 10 + max(0, min(seats, 200) - 50) * 7 + max(0, seats - 200) * 5
banded_rev = sum(banded(seats) * teams for seats, teams in mix)
print("break-even seats", FLAT / PER_SEAT)
print("monthly revenue: per-user", per_user, "flat", flat, "per-user capped at 500", capped)
# Flat revenue = FLAT x (600 x x + 300 x 0.70 + 80 + 20), where x is the share of 5-seat teams that buy.
# Setting that equal to per_user and solving for x gives:
needed = (per_user / FLAT - 300 * 0.70 - 80 - 20) / 600
print("per-user with seat bands:", banded_rev, "; cost vs uncapped:", per_user - banded_rev)
print("300-seat teams (at $3,000) that would have to leave for uncapped to equal banded:", round((per_user - banded_rev) / 3000, 1))
print("flat matches per-user if 5-seat teams buying is at least", round(needed, 3))
Output:
break-even seats 50.0
monthly revenue: per-user 198000 flat 230000.0 per-user capped at 500 140000
per-user with seat bands: 176600 ; cost vs uncapped: 21400
300-seat teams (at $3,000) that would have to leave for uncapped to equal banded: 7.1
flat matches per-user if 5-seat teams buying is at least 0.143
So under these guesses the flat fee earns $230,000/month against $198,000 for per-user, but only because mid-size teams pay more than they do today. Where the 14.3% comes from: flat revenue is $500 x (600 x x + 300 x 0.70 + 80 + 20), where x is the share of 5-seat teams that buy, the 300 x 0.70 is the 70% of 20-seat teams that buy, and the 80 and 20 are the 60- and 300-seat teams that all buy. That equals $300,000 x x + $155,000. Setting it equal to the per-user $198,000 gives x = 43,000 / 300,000 = 0.143. If fewer than about 14.3% of 5-seat teams buy at $500, flat falls below per-user (all other buy rates held at the guesses above).
Two ways to give large accounts a better deal. A hard cap at $500 earns $140,000 because every team above 50 seats is frozen at $500, which gives away the most revenue and removes expansion beyond 50 seats. Seat bands (here $10 for the first 50 seats, $7 for seats 51 to 200, $5 above 200) earn $176,600: a 300-seat team pays $2,050 instead of $3,000 (500 + 150 x 7 + 100 x 5), a 500-seat team pays $3,050 (500 + 1,050 + 300 x 5), and teams keep paying more as they add seats. Bands cost $21,400 a month against uncapped per-user, so they pay for themselves only if they stop roughly 7 of the 20 largest teams ($3,000 each) from leaving or negotiating hard; that is the number to test.
Customer value, churn and sales
- Per-user: price tracks value (seats are a proxy for the value delivered), so expansion is automatic as teams hire, giving net revenue retention above 100% (NRR: revenue from the same customers a year later as a share of what they paid now). The risk is contraction (customers cutting seats, for example after layoffs) and seat-count gaming, such as shared logins (several people using one paid seat). Churn is highest in teams with many idle seats, so watch seat utilisation (the share of paid seats actually in use).
- Flat: predictable bills and an easy sale, but no automatic expansion and large teams are underpriced (a 300-seat team pays $1.67 per seat). Small teams may feel they overpay at $100 per seat and churn or never convert. Churn is lower for big teams (they got a deal) and higher for small ones.
- Sales: per-user needs a seat forecast and invites seat negotiation. Flat shortens the cycle and needs fewer approvals, but gives sales nothing to expand besides a second plan.
Recommendation and what would flip it
Choose per-user pricing with seat bands for large teams (as above, not a hard $500 cap), test it on new customers, and keep flat only as an annual-commit option. This is a choice of expansion and defensibility over the $32,000 higher revenue the flat model shows under guessed buy rates: that lead rests on mid-size teams paying 2.5 times more and on small teams buying at all, which are the least certain inputs. Flip towards the flat fee if data show seat-counting causes friction (deals stall on seat counts) and large teams rarely exceed a few dozen seats. The input to validate first is the buy rate of the smallest teams at $500, since that single assumption decides the revenue comparison.
The product team proposes a 5% increase in the base fare on a two-sided marketplace. As an analyst, which metrics would you simulate to estimate the impact on demand, revenue, supply-side participation and customer satisfaction? Outline the experiment or modelling approach you would use to validate the change before full rollout.
Sample Answer
Direct answer
Before shipping the 5% base-fare increase I would first simulate it with a simple demand model, then validate it with a geography-and-time experiment (a geo experiment gives different regions different prices; a switchback alternates one region between prices over time blocks) rather than a rider-level A/B test. The metrics to simulate fall in four groups: demand (requests, conversion, completed trips), revenue (GMV, which is gross merchandise value, the total fares paid; and net revenue after the platform's take rate, its percentage cut), supply participation (online hours, acceptance, earnings per hour) and satisfaction (ratings, repeat rate, complaints). The key unknown is price elasticity of demand: the percentage change in trips for a 1% change in price. It is negative: an elasticity of -1 means a 1% price rise loses about 1% of trips.
Step 1: simulate before testing
Use a constant-elasticity model: trips after = trips before x 1.05^e, where e is the elasticity (negative). Illustrative inputs: 100,000 trips per week, an average fare of $20, a 25% take rate (platform revenue is 25% of GMV), and fares rising 5% to $21.
| Elasticity e | Trips/week | Change | GMV | Change | Platform revenue (25%) |
|---|---|---|---|---|---|
| -0.4 | 98,067 | -1.9% | $2.059M | +3.0% | $514.9k |
| -0.8 | 96,172 | -3.8% | $2.020M | +1.0% | $504.9k |
| -1.0 | 95,238 | -4.8% | $2.000M | 0.0% | $500.0k |
| -1.5 | 92,943 | -7.1% | $1.952M | -2.4% | $488.0k |
Baseline GMV is 100,000 x $20 = $2.000M and platform revenue is $500k. Reading it: when demand is less elastic than -1 the increase raises GMV, at -1 it is neutral, and beyond -1 it loses money. Pull the plausible range of elasticity from past price changes, promotions and surge-price episodes, and carry the whole range through, since the answer is most sensitive to it.
The supply side changes the picture. Decide who receives the extra fare: if it goes to providers (drivers, hosts, sellers), take rate falls but supply hours and acceptance should rise, shortening waits and partly offsetting the demand loss. If the platform keeps it, take rate rises and supply gets no new reason to show up. Simulate both splits. At e = -0.8 (96,172 trips a week at $21; today providers receive $15 a trip and the platform $5), the table above splits the extra dollar in proportion (platform $5.25 a trip, $504.9k). At the extremes: if the platform keeps the extra dollar it earns $6 a trip, 96,172 x 6 = $577.0k a week (+15.4% against $500k, take rate 28.6%) with no new reason for supply to show up; if providers get it they earn $16 a trip (+6.7%) and the platform earns $5, 96,172 x 5 = $480.9k (-3.8%, take rate 23.8%), the price of attracting more provider hours and shorter waits, which the experiment must then measure. Also check what share of the all-in price the base fare is: if fees and taxes sit on top, a 5% base increase is a smaller percentage change to what the customer pays, so the elasticity must be applied to the all-in price.
Metrics tree
| Group | Primary | Guardrail (must not get worse) |
|---|---|---|
| Demand | Completed trips per 1,000 active users, request-to-completion rate | Cancellation rate |
| Revenue | Net revenue per available provider hour | Take rate stays inside an agreed band |
| Supply | Provider online hours, earnings per hour, acceptance rate | Provider churn |
| Satisfaction | Repeat rate at 28 days, rating, support contacts | Complaints about price |
| Marketplace health | Fill rate (share of requests matched), wait time | Wait time stays below its limit |
Step 2: validate with an experiment
Randomising individual customers is unsafe here because treated and untreated customers share the same pool of providers. A user-level test relies on SUTVA (stable unit treatment value assumption: one unit's outcome does not depend on which arm other units are in). It fails in marketplaces, which biases the result.
- Design: a switchback or geo experiment. Randomly assign comparable regions (or time windows within a region, such as alternating blocks) to the new fare or the current fare, stratified by region size and day of week (first group regions or time windows of similar size and day of week, then randomise within each group, so both arms are alike).
- Duration: long enough for providers to react (supply adapts over weeks, not hours) and to see repeat behaviour, with a washout between switchback blocks (a gap whose data is discarded) so effects do not carry over.
- Analysis: compare regions with cluster-robust standard errors (error bars that treat all rows from one region as one correlated unit, because trips in a region are not independent); check pre-period balance (that treated and control regions behaved alike in the weeks before the test); report revenue per provider hour and trips with intervals.
- Guardrails: an automatic stop if wait time, cancellations or provider hours cross a pre-set line.
- Worked example (illustrative): 40 regions in 20 matched pairs by size, one region of each pair randomly given +5%, a 4-week pre-period and a 6-week test. If region-level noise in the change in trips, after adjusting for the pre-period, has a standard deviation of 4%, then 20 regions per arm can detect a difference of (1.96 + 0.8416) x sqrt(2 x 0.04^2 / 20) = 3.5%. The simulated trip loss at e = -0.8 is 3.8%, so it is just detectable; the 1% GMV effect is not, since it would need 2 x 7.849 x 0.04^2 / 0.01^2 = about 251 regions per arm. So size the test on trips, and judge revenue through the estimated elasticity: the price rise is worth shipping if the estimated trip loss is smaller than the 4.8% at which GMV is neutral (e = -1, since 1.05^-1 = 0.952).
- Decision rule: ship if net revenue per provider hour improves and no guardrail breaks; if demand loss is bigger than the simulation predicted, update the elasticity and re-run.
Pitfalls: novelty effects (people react to anything new) and price-anchoring effects (people judge later prices against the first one they saw) fade, so read week 1 cautiously; fare changes interact with promotions running at the same time; and a 5% change is small, so the experiment needs enough regions to detect it.
Unlock Full Question Bank
Get access to all 23 Pricing Strategy and Business Model interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.