Business Metrics and Unit Economics Questions
The economics of how a business makes money, computed at the per-customer and per-unit level. Covers customer acquisition cost (blended and by channel, including which spend to include and how to allocate shared costs), customer lifetime value (simple, cohort-based, discounted, and probabilistic or censored-data estimates such as Pareto/NBD and Monte Carlo uncertainty), LTV:CAC ratio and CAC payback period, ARPU and ARPPU, gross, contribution and operating margin, and cost allocation across units. Includes subscription revenue metrics (MRR, ARR, expansion, contraction, customer versus revenue churn and net revenue retention, and how revenue recognition, discounts and refunds affect reported figures), marketplace and delivery economics (take rate, GMV, per-order contribution, supply-side value, break-even), cohort revenue curves, and sensitivity analysis on churn, price and acquisition cost. Reasons about what moves these numbers and whether growth is efficient: diagnosing a falling LTV, a rising CAC or a shrinking margin, deciding whether to scale a channel or segment, and presenting unit economics to executives. Includes SQL and spreadsheet implementations of these calculations. Also covers the growth-metric vocabulary and its arithmetic: AARRR metric mapping, activation-rate definitions, viral coefficient (K-factor) and referral conversion math, and churn and retention rate formulas, defined and computed as inputs to unit economics rather than as growth interventions. Metric governance, dashboard and pipeline engineering, attribution, experimentation, forecasting method and pricing strategy are covered elsewhere.
You are evaluating a SaaS customer's platform choice. How would you show how an architecture proposal affects CAC, LTV, gross margin and payback? Work a short example in which better uptime and faster feature delivery lower churn and so raise LTV.
Sample Answer
Direct answer
Translate the architecture proposal into the four commercial levers that unit economics tracks, assign each a measurable mechanism, compute before and after on one consistent basis, and be honest about what moves in the wrong direction. Unit economics here means the profit and cost of one customer account. Account here means one customer organisation. CAC (customer acquisition cost) is the cost to win a new account, LTV (lifetime value) is the gross profit an account is expected to generate before it leaves, gross margin is revenue minus cost of serving it, and payback is the number of months of gross profit needed to recover CAC. A better platform lowers churn (which raises LTV) and may improve win rates (the share of sales opportunities that become customers, which lowers CAC), but redundancy and richer infrastructure usually cost margin. The customer needs to see the net.
Mechanisms, and the evidence for each
| Lever | How the architecture moves it | Evidence to collect |
|---|---|---|
| Churn | Better uptime means fewer incidents and fewer service credits (refunds a provider owes when it misses its uptime promise). Faster feature delivery closes gaps that customers cancel over | Churn-reason tags, incidents per account in the 90 days before cancellation, churn of accounts with a severe incident against matched accounts (comparable accounts without one) |
| Gross margin | Extra redundancy and tooling raise cloud and operating cost per account | Cloud bill per account before and after, engineering hours on support |
| CAC | Reliability and features win more deals and shorten sales cycles (the time from first contact to signed deal) | Win and loss reasons, sales-cycle length, deals lost on named gaps |
| Payback | Depends on CAC and gross margin only, not on churn | Computed |
Worked example (illustrative accounts)
An account pays $2,000 per month (ARPA, average revenue per account), CAC is $24,000, gross margin is 70% and monthly churn 2.5%. The proposal moves availability from 99.5% to 99.9% (a 30-day month has 720 hours, so downtime falls from 0.5% x 720 = 3.6 hours to 0.1% x 720 = 0.72 hours, about 43 minutes) and speeds up delivery. Assume churn falls to 2.0%, of which 0.3 points is uptime and 0.2 points is feature velocity (a split to be replaced with evidence: tag each cancellation with its stated reason, count severe incidents in the 90 days before it, and check whether the missing feature named in the cancellation was on a delivered roadmap item), while margin falls to 68% because of the extra cost.
ARPA, CAC = 2000.0, 24000.0 # ARPA = average revenue per account per month; CAC per new account
def metrics(gm, churn, cac=CAC):
ltv = ARPA * gm / churn
return ltv, ltv / cac, cac / (ARPA * gm)
for name, gm, ch, cac in [("current", 0.70, 0.025, CAC), ("proposal", 0.68, 0.020, CAC),
("proposal, churn only 2.3%", 0.68, 0.023, CAC),
("proposal, churn 2.0% and CAC 22,000", 0.68, 0.020, 22000.0)]:
l, r, p = metrics(gm, ch, cac)
print(f"{name:40s} LTV ${l:,.0f} LTV:CAC {r:.2f} payback {p:.1f} mo")
print(f"break-even churn at 68% margin: {ARPA*0.68/metrics(0.70,0.025)[0]:.2%}")
current LTV $56,000 LTV:CAC 2.33 payback 17.1 mo
proposal LTV $68,000 LTV:CAC 2.83 payback 17.6 mo
proposal, churn only 2.3% LTV $59,130 LTV:CAC 2.46 payback 17.6 mo
proposal, churn 2.0% and CAC 22,000 LTV $68,000 LTV:CAC 3.09 payback 16.2 mo
break-even churn at 68% margin: 2.43%
Reading it:
- LTV rises from $56,000 to $68,000 (+$12,000 per account) and LTV:CAC from 2.33 to 2.83. Judge those ratios against the customer's own target: many teams set a threshold such as 3x, but that is a policy choice, not a standard. Against a 3x target both 2.33 and 2.83 fall short, and only the case where CAC also falls to $22,000 (3.09) clears it.
- Payback gets slightly worse, from 17.1 to 17.6 months, because margin fell and CAC did not. Say so: payback ignores churn, so it does not capture the benefit.
- The assumption it is most sensitive to is the churn reduction. At 68% margin the proposal only breaks even on LTV if churn falls below 2.43%. If churn falls only to 2.3%, LTV is $59,130, a gain of 5.6%.
- If better delivery also improves win rates so CAC falls to $22,000, LTV:CAC reaches 3.09 and payback improves to 16.2 months.
For the investment decision, multiply the per-account gain by accounts it applies to: for example 300 new accounts a year at +$12,000 is $3.6 million of lifetime gross profit (undiscounted, meaning later dollars are not reduced for the time value of money; illustrative), set against the one-time build and migration cost, and the same churn gain also applies to existing accounts and should be counted separately.
Recommendation and pitfalls
Recommend the proposal if the evidence shows a reliability-attributable share of churn large enough to bring churn below the break-even, and commit to measuring churn on migrated accounts. What would change the call: a margin hit far larger than the 2 points assumed (with churn at 2.0% the proposal only stops beating the current LTV of $56,000 if margin falls to 56%, and with churn at only 2.3% if it falls below about 64.4%; the second case is why the churn evidence matters more than the margin estimate), churn reasons that point to price or fit instead of reliability, or a CAC effect that is only anecdotal. Pitfalls: crediting every churn reduction to the architecture when sales and product also changed, comparing LTV on a different margin basis before and after, and quoting uptime percentages without mapping them to hours of downtime in the customer's terms.
Which costs would you put in COGS and which in operating expenses when calculating gross margin for a SaaS product? Consider hosting, payment fees, direct support and onboarding credits, and justify each classification.
Sample Answer
Direct answer
COGS (cost of goods sold) holds the costs that rise when you serve more customers and that you would still incur to deliver the service as it exists today: production hosting, payment processing fees, and support for existing customers. Operating expenses (opex) hold the costs of building the product, finding customers and running the company. Gross margin = (revenue - COGS) / revenue. The consistent rule I apply: if the cost exists to deliver the paid service to current customers, it is COGS; if it exists to build or to win, it is opex.
Classification of the four named items
| Item | Classification | Why |
|---|---|---|
| Hosting | Production hosting is COGS. Development, test and staging environments are R&D (research and development) opex | Production runs the paid service; dev and test exist to build it |
| Payment fees | COGS in most SaaS (software as a service) reporting | They scale with every dollar billed and are unavoidable to collect revenue. Some firms report them in opex; if so, the margin is not comparable |
| Direct support | Support for paying customers is COGS. Pre-sales support and sales engineering are sales and marketing opex | Support for existing customers is part of delivering the service; pre-sales exists to win deals |
| Onboarding credits | Treat as a reduction of net revenue (the customer never pays that amount), while the hosting they consume stays in COGS. Do not also book the credit as an expense | A credit given in place of a price is a discount. Counting it as both a cost and a revenue reduction double counts |
Two judgement calls to state explicitly: implementation or onboarding staff working on contracted customers are COGS, whereas time spent before the contract is sales and marketing; support and hosting for a free tier (the unpaid plan) is a choice (acquisition cost in sales and marketing, or COGS) that must be applied the same way every period. Check how finance reports these lines so the product's number reconciles with the reported one.
Worked example (illustrative, one month, $k)
Billed revenue 510, onboarding credits 10, so net revenue 500. COGS: production hosting 60, payment fees 14, direct support 50, onboarding staff 20, total 144.
Gross margin = (500 - 144) / 500 = 71.2%. Dev and test hosting (15) and pre-sales support (14) sit outside COGS.
How each misclassification moves the number:
| Treatment | Gross margin |
|---|---|
| Classification above | 71.2% |
| Payment fees moved to opex | 74.0% |
| Dev and test hosting wrongly put in COGS | 68.2% |
| Pre-sales support wrongly put in COGS | 68.4% |
| Credits ignored (revenue left at 510) | 71.8% |
| Credit also booked as a $10k cost (double count) | 69.2% |
Reconciling with the reported number: suppose finance reports 68.4% against your 71.2%. The gap is 2.8 points of $500k, which is $14k, exactly the pre-sales support, so finance has put pre-sales support in COGS. Closing the gap line by line like this tells you which policy differs, not which number is wrong.
Why it matters for the roles that use the number
A margin that omits payment fees or credits makes unit economics (profit per customer) look better than they are, because LTV (lifetime value, the total gross profit a customer is expected to generate) is built on gross margin, so pricing and acquisition decisions get made on the wrong figure. For a solutions architect, per-tenant (per-customer account) hosting cost should be tagged so production COGS can be measured by customer instead of allocated (split in proportion to each customer's revenue rather than measured).
Pitfalls
- Moving a cost between COGS and opex to flatter margin; the test is consistency across periods.
- Ignoring credits, which overstates both revenue and margin.
- Comparing your margin with another company's without checking how it classifies payment fees and support.
What is the difference between MRR and ARR, and how do you convert between them? Name three pitfalls when reporting ARR for products with annual prepayment, usage-based billing or multi-year contracts.
Sample Answer
Direct answer
MRR (monthly recurring revenue) is the monthly value of active recurring contracts; ARR (annual recurring revenue) is the same value on a 12-month basis. Convert with ARR = MRR x 12 and MRR = ARR / 12. They describe the same run-rate (today's recurring revenue expressed over a year); ARR is the usual headline for annual-contract businesses and MRR for monthly-billed ones. The risk is in what you count: ARR is a measure of recurring contract value at a point in time, not cash collected (billings), not revenue recognised (the portion of a contract that accounting treats as earned so far), and not total contract value.
Worked example (three contracts)
| Contract | Billing | MRR | ARR |
|---|---|---|---|
| A: $5,000 per month, billed monthly | Monthly | $5,000 | $60,000 |
| B: $120,000 paid once for a one-year term | Annual prepay | $10,000 | $120,000 |
| C: two-year contract billed at $100,000 per year | Multi-year | $8,333.33 | $100,000 |
| Total | $23,333.33 | $280,000 |
Check: 60,000 + 120,000 + 100,000 = 280,000, and 280,000 / 12 = 23,333.33.
Three pitfalls
- Annual prepayment. Contract B brings $120,000 of cash in one month, but its MRR is $10,000 from month one and each following month. Reporting the cash as MRR in the billing month (a $120,000 spike followed by zero) overstates growth, then understates it. Count the normalised monthly value, and keep billings (invoiced cash) and deferred revenue (cash received for service not yet delivered) as separate metrics. For contract B, month one shows billings of $120,000, recognised revenue of $10,000, deferred revenue of $110,000 left at month end, and MRR of $10,000.
- Usage-based billing. Revenue varies month to month, so annualising one busy month (for example, peak-season usage times 12) overstates ARR. Use a trailing average (say, the last 3 months) or only the committed minimum as ARR, and label usage above the commitment as usage run-rate, because it is not contractually recurring. Illustration: a customer has a $2,000 monthly committed minimum and spends $2,800, $3,500 and $4,200 in the last three months, with a peak month of $6,000. Peak x 12 = $72,000 overstates; the trailing 3-month average is $3,500, so usage run-rate is $42,000; the committed minimum alone is $24,000 ($2,000 x 12).
- Multi-year contracts. Contract C has total contract value (TCV) of $200,000, but ARR is $100,000, the annual value. Adding the full $200,000 to ARR double counts. The same applies to ramped deals (year one $80,000, year two $120,000): ARR at signing is the current year's rate; the ramp is disclosed, not blended unless the policy says so. At signing the reported ARR is $80,000; in year two it becomes $120,000, and the dashboard can note the contracted step-up separately.
Policy choices to document
Treat one-time fees, implementation and overages as non-recurring; use the discounted price; fix a currency conversion rate; decide when a cancelled-but-still-active customer leaves ARR. Reviewers who see two companies' ARR should ask for these rules before comparing.
Why it matters to solution design
When a deal is structured as a multi-year commitment with an upfront payment, the ARR a customer is credited with changes nothing about their usage, but it changes how sales, finance and customer-success views of that account line up. Take contract C stretched to two years paid upfront ($200,000 cash on day one). Sales may quote $200,000 of total contract value as the bookings figure; finance sees $200,000 of billings, $8,333 of revenue recognised per month and a deferred revenue balance of about $191,667 after month one; customer success sees ARR of $100,000, the annual value they are responsible for retaining. Same deal, three different numbers, each correct for its purpose. A solutions architect scoping contract structure should know which number each team will read from it, and should choose billing terms (upfront, annual, ramped) with that in mind.
Design the metrics and instrumentation to compute product-level and feature-level profitability. Which data sources (billing, usage telemetry, infrastructure cost) do you need, what rules allocate shared platform costs, and how do you present margin per product to executives without false precision?
Sample Answer
Direct answer
Product and feature profitability means revenue minus the costs that product causes, with shared platform costs allocated by a stated rule. Build it in three layers: (1) trace revenue and direct costs to each product from billing and tagged infrastructure cost; (2) allocate shared platform cost using usage telemetry as the driver, one driver per cost pool (a bucket of shared cost, such as the API gateway bill); (3) present a rule-free contribution margin first (revenue minus the costs directly traceable to the product, before any shared cost), then the after-allocation margin as a range across plausible allocation rules, rounded, with a note on how complete the cost tagging is. The ranking of products can change with the rule, so the honest executive message is the margin range and whether the ranking is stable, not a single precise figure.
Data sources and what each provides
| Source | Gives | Key fields / risks |
|---|---|---|
| Billing and subscription system | Revenue per customer and plan | Bundled plans have no per-product price: revenue must be split by a stated rule (list price ratio or usage) |
| Usage telemetry (product events, API calls, storage) | The allocation driver | Every event needs product_id, feature_id and tenant_id (which customer account it came from); unmetered features cannot be allocated |
| Cloud and infrastructure cost (billing export with cost-allocation tags, which are labels on cloud resources saying which product they serve, and Kubernetes namespace costs, the compute cost of each team's group of services) | Direct and shared infrastructure cost | Untagged spend; report the share of cost that is tagged |
| Third-party and metered vendor cost (fees billed per use) | Direct cost (for example per-call model or messaging fees) | Often invoiced by vendor, not by product |
| Support, on-call (engineers paid to respond to incidents) and platform engineering cost | Shared service cost | Tickets and incidents are only useful if labelled by product |
Terms: a direct cost is traceable to one product; a shared platform cost (authentication, the API gateway that routes every request, observability meaning logging and monitoring, and on-call) supports several products; showback means reporting each team's cost without charging it, which is how I would start.
Allocation rules: one driver per pool
| Shared cost pool | Allocation driver |
|---|---|
| API gateway | request count |
| Storage platform | GB stored |
| Observability | log or metric volume |
| Authentication | monthly active users |
| On-call and incident response | incident count |
| Unattributable overhead | held in a separate "unallocated" line, not forced onto products |
Worked line for one pool (illustrative): a $100k API gateway cost split by request count. If Analytics made 15% of the requests it carries 0.15 x $100k = $15k of that pool.
Document each rule: the driver, the data source, the period, who approved it. Freeze the rules for at least a quarter, so a change in margin reflects the business and not a new rule.
Worked example: how much the rule matters
Three products with revenue and direct cost in $ thousands a month (illustrative), and a $400k shared platform cost. The usage share column is each product's measured share of platform compute: for example, if the platform's compute metering shows 150, 550 and 300 compute-hours for the three products in the month, the shares are 15%, 55% and 30%.
# Monthly figures, $ thousands (illustrative). Direct cost = cost-tagged infrastructure + metered third-party usage.
products = {
# revenue, direct cost, share of shared-platform compute (telemetry)
"Analytics": dict(rev=900, direct=270, usage=0.15),
"Messaging": dict(rev=600, direct=210, usage=0.55),
"Reporting": dict(rev=300, direct=60, usage=0.30),
}
SHARED = 400 # shared platform cost: auth, gateway, observability, on-call, $k per month
total_rev = sum(p["rev"] for p in products.values())
rules = {
"revenue share": lambda p: p["rev"]/total_rev,
"usage share": lambda p: p["usage"],
"equal split": lambda p: 1/len(products),
}
print(f"shared cost ${SHARED}k, total revenue ${total_rev}k")
for rule, share in rules.items():
out = []
for name, p in products.items():
alloc = SHARED * share(p)
margin = (p["rev"] - p["direct"] - alloc) / p["rev"]
out.append((margin, name, alloc))
out.sort(reverse=True)
print(f"\n{rule}:")
for margin, name, alloc in out:
print(f" {name:<10} allocated ${alloc:6.1f}k margin after allocation {margin:6.1%}")
print(" ranking:", " > ".join(n for _, n, _ in out))
print("\ncontribution margin before any shared allocation (rule-free):")
for name, p in products.items():
print(f" {name:<10} {(p['rev']-p['direct'])/p['rev']:.1%}")
Output:
shared cost $400k, total revenue $1800k
revenue share:
Reporting allocated $ 66.7k margin after allocation 57.8%
Analytics allocated $ 200.0k margin after allocation 47.8%
Messaging allocated $ 133.3k margin after allocation 42.8%
ranking: Reporting > Analytics > Messaging
usage share:
Analytics allocated $ 60.0k margin after allocation 63.3%
Reporting allocated $ 120.0k margin after allocation 40.0%
Messaging allocated $ 220.0k margin after allocation 28.3%
ranking: Analytics > Reporting > Messaging
equal split:
Analytics allocated $ 133.3k margin after allocation 55.2%
Messaging allocated $ 133.3k margin after allocation 42.8%
Reporting allocated $ 133.3k margin after allocation 35.6%
ranking: Analytics > Messaging > Reporting
contribution margin before any shared allocation (rule-free):
Analytics 70.0%
Messaging 65.0%
Reporting 80.0%
| Product | Before allocation | Revenue share rule | Usage share rule | Equal split |
|---|---|---|---|---|
| Analytics | 70.0% | 47.8% | 63.3% | 55.2% |
| Messaging | 65.0% | 42.8% | 28.3% | 42.8% |
| Reporting | 80.0% | 57.8% | 40.0% | 35.6% |
| Ranking | Reporting, Analytics, Messaging by contribution (80, 70, 65) | Reporting > Analytics > Messaging | Analytics > Reporting > Messaging | Analytics > Messaging > Reporting |
The ranking is unstable: Reporting is first under one rule, second under another and last under the third, and Messaging ranges from 28.3% to 42.8%. That is the sensitivity result I would put in front of executives.
Presenting without false precision
- Lead with contribution margin before shared cost, which has no allocation rule in it, then show margin after allocation.
- Show the range across rules rather than one number, and round to the nearest 5 points. Here Messaging would be reported as "about 30 to 45%".
- Say which conclusions survive every rule (Messaging is not the best product under any of them) and which do not (the order of Analytics and Reporting).
- State data completeness: what share of cloud cost carries a product tag, what share of revenue was split by assumption (bundles), which products have no metering.
- Feature-level margin follows the same method but with a much weaker revenue link, since a bundled price is not earned by one feature. Report feature-level cost, and usage-weighted margin only as a labelled estimate. For a bundle, a $1,000 monthly plan whose parts list at $600 and $400 is split 60/40 by list price, or by each part's measured usage.
- Worked example (illustrative, $ thousands a month): Messaging earns 600 and has 210 of direct cost from vendor invoices, which the metering splits into Chat 180 and Email 30. Splitting the 600 by usage (70% Chat, 30% Email) gives Chat 420 of revenue and a contribution margin of (420 - 180) / 420 = 57%, and Email 180 and (180 - 30) / 180 = 83%. Splitting the 600 by list price 50/50 instead gives Chat (300 - 180) / 300 = 40% and Email (300 - 30) / 300 = 90%. The revenue rule alone moves Chat by 17 points, so feature margins are shown as ranges.
Pitfalls
- Allocating shared cost by revenue punishes successful products and can hide a costly one.
- Treating untagged cost as zero; report it separately.
- Changing a driver mid-year and reporting the resulting margin shift as performance.
- Using the allocation to decide pricing or sunsetting without testing the decision against the rule-free contribution margin.
That is every published Business Metrics and Unit Economics question for Solutions Architect so far. Browse the other topics in this category, or practice this one interactively.