Business Acumen and Commercial Context Questions
Reasoning about how a business earns and spends money, and judging the commercial consequence of a decision from the candidate's own seat, at a generic (company-agnostic) level. Covers translating technical, product or data work into revenue, cost, margin and risk terms: model accuracy, precision and recall choices and decision thresholds priced in dollars; latency, availability and incident downtime turned into revenue at stake; build-versus-buy, vendor, architecture, multi-region, single-tenant and technical-debt decisions weighed commercially. Also covers trade-offs such as growth versus profitability, speed versus cost, engagement versus revenue, and opportunity cost and the cost of delay between competing investments; how an engineering, data or platform function creates and demonstrates business value, including indirect contributions; connecting functional plans and OKRs to company strategy and revenue goals; and explaining the commercial case to non-technical leaders and finance partners, with stated assumptions and uncertainty. Tests whether a candidate can tie day-to-day choices to commercial outcomes and explain that link clearly. Full investment business cases, KPI design, computing unit economics, pricing decisions, case-interview frameworks and researching a specific company are covered elsewhere.
You must choose between two models. Model A is 6 points more accurate than baseline, takes 200ms and costs $0.002 per prediction. Model B is 4 points more accurate, takes 100ms and costs $0.0005 per prediction. Baseline conversion is 2%, revenue per conversion is $10 and traffic is 1M requests a day. How do you decide, and what would change your answer?
Sample Answer
Direct answer
Decide on expected net value per day, not accuracy: translate each model's gain into conversions, price them, subtract serving cost, and then test how fragile the result is. With the stated numbers and one stated assumption (below), Model A nets about $2,500 a day more than Model B, so A wins, but the margin is thin enough that three things could flip it: A's extra 100 ms hurting conversion by about 1.2% or more, the accuracy gain translating into less lift than assumed, and the $10 being revenue rather than profit (contribution margin, the share of revenue left after variable costs such as payment fees and shipping). I would pick A provisionally and confirm with an A/B test on conversion and latency.
The key assumption, stated openly
Accuracy points are not conversion points. I treat "6 points" and "4 points" as relative conversion lifts of 6% and 4% over the 2% baseline, as a placeholder; a real answer replaces it with lifts measured in an experiment. If the points were absolute conversion points (2% to 8%) the numbers would be implausible, which is itself a reason to measure.
Worked arithmetic
Baseline: 1,000,000 requests/day x 2% = 20,000 conversions x $10 = $200,000/day. Conversion means a request ends in a purchase.
- Model A: +6% x 20,000 = 1,200 extra conversions = $12,000, minus 1,000,000 x $0.002 = $2,000 serving cost, net +$10,000/day.
- Model B: +4% x 20,000 = 800 extra conversions = $8,000, minus 1,000,000 x $0.0005 = $500, net +$7,500/day.
- Stepping from B to A costs $1,500 more per day for $4,000 more revenue.
The script below prints three separate tables: first A against B including the latency penalty (the question asked), then a real-time versus batch comparison that is explained in its own section further down, then how the A versus B result changes if the $10 is revenue and only a share is contribution margin.
REQUESTS = 1_000_000
BASE_CONV = 0.02
REV_PER_CONV = 10.0
base_conversions = REQUESTS * BASE_CONV # 20,000 per day
def daily_net(relative_lift, cost_per_prediction, latency_penalty=0.0):
conversions = base_conversions * (1 + relative_lift) * (1 - latency_penalty)
return conversions * REV_PER_CONV - REQUESTS * cost_per_prediction
print(f"baseline revenue per day: ${base_conversions * REV_PER_CONV:,.0f}")
a, b = daily_net(0.06, 0.002), daily_net(0.04, 0.0005)
print(f"A net uplift/day ${a - base_conversions*REV_PER_CONV:,.0f} | B net uplift/day ${b - base_conversions*REV_PER_CONV:,.0f}")
for pen in (0.0, 0.005, 0.01, 0.0118, 0.015):
# A pays an extra latency penalty versus B (B is 100 ms faster)
print(f"extra conversion loss from A's slower response {pen:.2%}: A minus B = ${daily_net(0.06, 0.002, pen) - daily_net(0.04, 0.0005):,.0f}/day")
print("\nReal-time vs batch (2M requests/day, 0.5 vs 0.3 extra conversions per 100 requests)")
for profit in (5, 9.5, 10, 15):
rt = 2_000_000 * (0.005 * profit - 0.02)
batch = 2_000_000 * (0.003 * profit - 0.001)
print(f"profit per conversion ${profit:>5}: real-time ${rt:>9,.0f}/day batch ${batch:>9,.0f}/day")
print("\nIf the $10 is revenue and only a share is contribution margin")
for margin in (1.0, 0.5, 0.375, 0.30):
a = base_conversions * 0.06 * REV_PER_CONV * margin - REQUESTS * 0.002
b = base_conversions * 0.04 * REV_PER_CONV * margin - REQUESTS * 0.0005
print(f"margin {margin:>5.1%}: A ${a:>7,.0f}/day B ${b:>7,.0f}/day A minus B ${a - b:>6,.0f}/day")
Output:
baseline revenue per day: $200,000
A net uplift/day $10,000 | B net uplift/day $7,500
extra conversion loss from A's slower response 0.00%: A minus B = $2,500/day
extra conversion loss from A's slower response 0.50%: A minus B = $1,440/day
extra conversion loss from A's slower response 1.00%: A minus B = $380/day
extra conversion loss from A's slower response 1.18%: A minus B = $-2/day
extra conversion loss from A's slower response 1.50%: A minus B = $-680/day
Real-time vs batch (2M requests/day, 0.5 vs 0.3 extra conversions per 100 requests)
profit per conversion $ 5: real-time $ 10,000/day batch $ 28,000/day
profit per conversion $ 9.5: real-time $ 55,000/day batch $ 55,000/day
profit per conversion $ 10: real-time $ 60,000/day batch $ 58,000/day
profit per conversion $ 15: real-time $ 110,000/day batch $ 88,000/day
If the $10 is revenue and only a share is contribution margin
margin 100.0%: A $ 10,000/day B $ 7,500/day A minus B $ 2,500/day
margin 50.0%: A $ 4,000/day B $ 3,500/day A minus B $ 500/day
margin 37.5%: A $ 2,500/day B $ 2,500/day A minus B $ 0/day
margin 30.0%: A $ 1,600/day B $ 1,900/day A minus B $ -300/day
What would change the answer
Where 1.18% comes from: A's conversion revenue is 21,200 x $10 = $212,000 a day, and A leads B by $2,500, so A ties B when 1.18% of that revenue disappears ($212,000 x 0.0118 = $2,500).
| Change | Effect on A minus B |
|---|---|
| A's extra 100 ms of latency costs 1.0% of conversions | still +$380/day |
| ...costs about 1.18% (break-even, the point where A and B tie) | $0 |
| ...costs 1.5% | -$680/day |
| $10 is revenue and contribution margin is 37.5% | $0 |
| ...margin is 30% | B wins by $300/day |
| Lift is smaller than the accuracy gap implies | A's cost grows relative to its gain |
Also check tail latency (the slowest requests: a model that averages 200 ms may take 600 ms for its slowest 1%, which at 1,000,000 requests a day is 10,000 slow requests, and the extra conversion loss concentrates there), whether cost per prediction rises with traffic, and whether 200 ms breaks a latency limit (a service-level objective) in the product.
Real-time versus batch
A separate decision uses the same logic: when predictions are computed. This is a new scenario with its own numbers, not a continuation of A versus B. Suppose real-time (computed when the request arrives) costs $0.02 per request with a 0.5 conversion uplift per 100 requests, and a once-an-hour batch (precomputed) costs $0.001 per request with 0.3 per 100, on 2,000,000 requests a day. In per-request terms, 0.5 per 100 is 0.005 conversions and 0.3 per 100 is 0.003, which is where the 0.005 and 0.003 in the formula come from; P is the profit per conversion. Real-time wins when (0.005 - 0.003) x P > 0.02 - 0.001, that is P > $9.50 profit per conversion. Below that, batch is better; the table above shows batch ahead at $5 and real-time ahead at $10 and $15.
Communicating the trade-off to stakeholders
Do not say "A is more accurate". Say: "Model A is expected to earn about $2,500 more per day than B (roughly $0.9 million a year), but it is slower. If the extra 100 ms costs us more than about 1.2% of conversions, B is better. We will run a two-week test on 10% of traffic to measure that, and we will treat the $10 as profit only if finance confirms the margin." Show a small table of the three assumptions and the range of outcomes, and ask them to own the risk threshold. If no experiment exists yet to give the lift, run the table at a haircut: if only a third of the accuracy gap turned into lift (2% for A, 1.33% for B), A nets $4,000 - $2,000 = $2,000 a day and B nets $2,667 - $500 = $2,167 a day, so B wins by about $167. That shows how much the A recommendation depends on the lift assumption, and is the reason to measure it.
Pitfalls
- Mixing revenue and profit on the two sides of the decision.
- Reading accuracy as lift.
- Ignoring that fixed assumptions (traffic, cost per call) move; recompute when traffic doubles.
- Picking the cheapest model because cost is the visible number while the conversion gain dominates.
Tell me about a time you found a high-impact commercial opportunity in data that others had missed. How did you validate it, persuade stakeholders, and turn it into a change in the product or operations?
Sample Answer
Direct answer
A strong story has six beats: the signal in the data, why others missed it, how you sized it, how you proved it was real and not an artefact (a pattern produced by how the data was collected rather than by real behaviour), how you won over the people who had to act, and what actually changed in the product or operations, with the business result. The point is that you moved a decision, not that you found a chart. Below is the shape, with an illustrative case whose numbers are derived on the page so you can see the reasoning, not recite it.
The six beats
- Situation: a product with a free trial, where the team looked at overall trial-to-paid conversion and treated it as one number.
- The miss: nobody had split trials by early behaviour. Averages hid that one early action separated converters from non-converters.
- Sizing: turn the pattern into dollars before anyone asks.
- Validation: try to break your own finding (see the checks below).
- Persuasion: bring the people who own the surface, with a small, cheap test they can say yes to.
- Change and result: the shipped change, how you measured it against a control, and what you learned.
Illustration (invented numbers, derived in full)
Say 2,000 trials start each month. 35% connect a data source within 24 hours and 24% of those become paying accounts. The other 65% convert at 6%.
- Overall conversion: 0.35 x 0.24 + 0.65 x 0.06 = 0.084 + 0.039 = 12.3%, or 246 paying accounts a month.
- The gap between the groups is 18 points (24% minus 6%).
- A nudge that raises early connection by 8 points moves 160 more trials a month into the connected group (2,000 x 0.08). If the whole 18-point gap were causal, that is 28.8 extra accounts a month.
Validation (what makes it credible)
- Confounding (a third factor drives both things you are comparing): engaged users connect early and also convert, so the 18 points overstates the cause. Check the pattern holds inside segments (company size, acquisition channel) and that the action comes before the conversion decision.
- Haircut (deliberately discount an estimate for uncertainty): assume half the gap is causal, so 14.4 extra accounts a month; at an illustrative $1,200 ACV (yearly contract value) that is about $17,280 of new yearly revenue per monthly cohort.
- Test: randomly show an in-product prompt to half of the trials that have not connected by hour 4 and compare conversion. A holdout is the half that does not get it.
Persuasion
I took the one-slide version to the product owner of onboarding, led with their goal (conversion), showed the sizing with its haircut, and asked for a two-week test rather than a roadmap change. In words, the ask was: "Onboarding conversion is your goal. Trials that connect a data source on day one convert at 24% against 6%. If even half of that gap is causal, a prompt is worth about $17,000 of yearly revenue per monthly cohort. Can we show it to half of the unconnected trials for two weeks and stop if it shows nothing?" Engineering agreed because the prompt was a small change behind a feature flag (a switch that turns it on for chosen users only) and because the test could end with a clear yes or no.
What changed and what to say about the result
State the shipped change, the result against the holdout including the interval (the range of lifts the data is consistent with, usually 95%), and what you did next (rolled out, iterated, or stopped). With illustrative numbers: about 400 eligible trials per arm, 27 paying in the prompted arm (6.75%) and 24 in the holdout (6.0%), a difference of +0.75 points with a 95% interval of -2.6 to +4.1. The interval includes zero, so the honest report is "a small gain is plausible but not proven; we extended the test and kept the prompt behind the flag". If the lift came in below the haircut estimate, say so: reporting a smaller truthful result is more credible than a round claim.
Pitfalls
- Correlation presented as cause is the most common failure. Name the confounder yourself.
- A story that ends at "I found it" is an analysis story, not a commercial one.
- Do not quote precise metrics you cannot defend. Use your real numbers, with their basis stated.
- "Others had missed it" should be explained (why the data was invisible), not implied.
You have a churn-probability score for each customer and a retention offer that costs money. How would you choose the decision threshold, how would you estimate what each type of error costs, and what changes if the scores are poorly calibrated?
Sample Answer
Direct answer
Pick the threshold where contacting a customer stops losing money. If the score is a calibrated probability p (a score of 0.2 really means about 20 in 100 such customers churn), contact when p x save rate x value kept is greater than the offer cost, that is, when p is above cost / (save rate x value). Estimate the cost of each error from the economics of the offer, measure the save rate with a randomised holdout, and if the scores are poorly calibrated, do not apply the formula to the raw score: recalibrate first, or choose the threshold empirically on held-out data. To check calibration, group customers by score band and compare each band's average score with the share who really churned; they should match. Start with the break-even rule and that check. The recalibration methods (Platt scaling, isotonic regression) and the uplift model are specialist tools to reach for only if the check shows a problem or the offer itself changes behaviour.
Estimating what each error costs
Define the inputs: offer cost c = $15 per customer contacted; save rate s = 30% of contacted would-be churners retained; value kept V = $300 contribution (revenue minus variable cost, over the expected remaining lifetime, not annual revenue).
| Outcome | What happens | Dollar effect |
|---|---|---|
| Contacted, would have churned | saved with probability s | expected gain s x V minus c = $90 - $15 = $75 |
| Contacted, would have stayed (false positive) | offer wasted (plus any discount given away) | cost c = $15 |
| Not contacted, would have churned (false negative) | the saving was forgone | opportunity cost $75 |
| Not contacted, would have stayed | nothing | $0 |
So a false positive costs $15 and a false negative costs $75, and the break-even probability is cost of a false positive divided by the sum of both costs: 15 / (15 + 75) = 0.167. The save rate s is the hardest input: it must come from a randomised holdout (a random slice of at-risk customers who get no offer), because customers chosen by the model differ from customers in general.
Worked example: why calibration matters
Simulated 50,000 customers with a fixed seed. Each customer gets a true churn probability drawn from a skewed distribution (most are low, average about 8%), and whether they churned is decided by a random draw against it. The model's score is that true probability raised to the power 0.6, which pushes every probability upward (0.10 becomes 0.25), so the score is deliberately overconfident: a score of 0.34 corresponds to only about 17% real churn. The first half tunes the threshold, the second half evaluates it. The "reliability table" in the code compares each score band's average score with its realised churn.
import random
random.seed(7)
N = 50_000
COST = 15.0 # cost of one retention offer, dollars
SAVE = 0.30 # share of contacted would-be churners the offer retains
VALUE = 300.0 # contribution kept when a churner is retained, dollars
break_even_p = COST / (SAVE * VALUE)
customers = []
for _ in range(N):
true_p = random.betavariate(1, 11) # true churn probability, mean about 8%
churned = random.random() < true_p
raw_score = min(0.999, true_p ** 0.6) # overconfident: scores run too high
customers.append((raw_score, churned))
tune, test = customers[: N // 2], customers[N // 2 :]
def profit(rows, threshold):
contacted = [(s, c) for s, c in rows if s >= threshold]
churners = sum(1 for _, c in contacted if c)
return SAVE * VALUE * churners - COST * len(contacted), len(contacted), churners
print(f"break-even probability = {COST} / ({SAVE} x {VALUE}) = {break_even_p:.3f}")
p, n, ch = profit(test, break_even_p)
print(f"test half, naive threshold {break_even_p:.3f} on raw score: contacted {n}, churners hit {ch}, profit ${p:,.0f}")
print("score band customers mean score realised churn (tuning half)")
for lo, hi in [(0.0, 0.2), (0.2, 0.3), (0.3, 0.4), (0.4, 0.6), (0.6, 1.0)]:
rows = [(s, c) for s, c in tune if lo <= s < hi]
print(f"{lo:.1f}-{hi:.1f} {len(rows):>9} {sum(s for s,_ in rows)/len(rows):>10.3f} {sum(c for _,c in rows)/len(rows):>14.3f}")
best_t = max(range(1, 100), key=lambda t: profit(tune, t / 100)[0]) / 100
p2, n2, ch2 = profit(test, best_t)
print(f"threshold chosen on tuning half: {best_t:.2f}")
print(f"test half at that threshold: contacted {n2}, churners hit {ch2}, profit ${p2:,.0f}")
Output:
break-even probability = 15.0 / (0.3 x 300.0) = 0.167
test half, naive threshold 0.167 on raw score: contacted 14138, churners hit 1793, profit $-50,700
score band customers mean score realised churn (tuning half)
0.0-0.2 13540 0.114 0.031
0.2-0.3 6406 0.247 0.098
0.3-0.4 3328 0.343 0.166
0.4-0.6 1674 0.460 0.308
0.6-1.0 52 0.641 0.442
threshold chosen on tuning half: 0.35
test half at that threshold: contacted 3079, churners hit 744, profit $20,775
Read the output:
- The formula gives 0.167. Applied to the raw score, it contacts 14,138 customers in the test half and loses $50,700, because customers with a raw score of 0.2 to 0.3 really churn only about 10% of the time, below the 16.7% break-even.
- The reliability table (mean score against realised churn per band) shows the over-confidence. The band with mean score 0.343 realises 16.6% churn, which is the break-even, so the right raw-score threshold is near 0.34.
- Choosing the threshold on the tuning half (0.35) and evaluating on the untouched half contacts 3,079 customers and earns $20,775.
If the scores are poorly calibrated, there are three options: recalibrate on held-out data (Platt scaling fits a logistic curve to the scores; isotonic regression fits a monotone step function), then apply the formula; or sweep thresholds on held-out labels as above; or ignore probabilities and contact the top k customers by rank if the team has fixed capacity. Re-check calibration over time, because drift breaks it silently.
Variants and extensions
- Credit scoring. The costs become the interest margin forgone on a wrongly declined good borrower versus the loss given default (the amount lost when a borrower fails to repay) on a wrongly approved bad one, net of what the lender pays to fund the loan (the cost of capital). Illustrative numbers: a good borrower yields $200 of margin, a default loses $4,000. Approving is worth it when (1 - p) x $200 - p x $4,000 > 0, that is when the default probability p is below 200 / 4,200 = 4.8%. Regulation adds constraints: decisions must be explainable, and lenders usually need compliance review of any rule that treats groups differently. To catch unfair error patterns, compare error rates across groups, for example if good applicants from group A are wrongly declined 8% of the time and from group B 14% of the time, one threshold is not treating them alike. Take legal advice on what adjustments are permitted.
- Simulate cost curves. Plot expected profit against threshold under low, central and high values of c, s and V, and choose a threshold from the flat region that stays good across them, rather than the single peak of one assumption set.
- Soften false positives. Instead of one cut-off, send the clearly high scores the offer automatically, route a middle band (say 0.25 to 0.35) to manual review or a cheap business rule such as "only if the customer has had a support complaint", and do nothing below it.
Pitfalls
- Sweeping thresholds on the same data you report on overstates profit; always use a held-out set.
- The offer affects the label: customers who get it change behaviour, so re-score periodically on fresh data.
- Offers can nudge customers who would have stayed to demand discounts ("sleeping dogs"); an uplift model, which predicts the effect of the offer rather than the churn risk, handles this directly.
- Capacity and budget caps change the answer: contacting everyone above 0.167 may exceed what the team can handle.
You have been tuning a model for weeks and its offline score is still creeping upward. When do you stop optimising the model and put the effort somewhere else, and what signals tell you?
Sample Answer
Direct answer
Stop optimising when the expected online value of the next week of tuning drops below the value of the best alternative use of that week, or when gains fall inside the model's own run-to-run noise. A climbing offline score (the model's score on held-out historical data, measured before any customer sees it) is a weak reason to continue: it measures progress on one validation set (the held-out data used to compare versions), and what you want is progress online, meaning on live customers. Concretely, I time-box tuning, track the marginal gain per week, shrink it by how much offline gains have historically survived online, and compare with the next-best work.
Signals that tell you to stop
- Diminishing marginal gain. The gain per week of this project is shrinking: 0.020, 0.010, 0.006, 0.003...
- Gains inside the noise. Retrain the same model with a few different random seeds (the seed fixes the random initialisation and data shuffling). If scores differ by 0.002, a 0.0015 gain is indistinguishable from luck.
- Validation-set overfitting. Weeks of looking at the same validation set mean you are selecting for noise. The creeping score may be partly the validation set memorised by your choices. Check against an untouched holdout (data nobody has tuned against or even looked at) or a fresh time window.
- Weak offline-to-online link. Compare past launches: when offline score rose by X, how much did the business metric move? If the answer is "barely" or "inconsistently", more offline points buy little.
- Error analysis points elsewhere. Error analysis means reading a sample of the model's worst mistakes by hand and sorting them by cause. If they are mislabelled rows, missing features, or stale data, no architecture change fixes them (label noise sets a ceiling that no tuning passes).
- A different bottleneck is binding. Latency, coverage, data freshness, the UI that shows the result, or the decision rule applied to the score.
Worked example: a stop rule with numbers
Assumptions (illustrative, replace with your own history): half of an offline gain survives online; the best alternative is a data and label clean-up expected to give 0.008 offline-equivalent over two weeks (0.004 per week); seed noise is 0.002.
"Offline-equivalent" means the clean-up's expected benefit is stated in the same units as the tuning gains, the offline score, so the two projects can sit in one table. The 0.008 is an estimate, not a measurement: for example, a quick audit finds 3% of training labels are wrong, and a comparable clean-up on a past model raised the score by about 0.004 for every 1.5% of labels fixed, giving 0.008 for 3%. What a 0.01 gain is worth in business terms comes from your launch history: if past launches show each 0.01 of offline score moved conversion by about 0.05 points, then 0.01 is worth about that much, and after the 50% shrink about half of it.
SHRINK = 0.5 # assume half of an offline gain survives online (check on past launches)
ALT_GAIN_PER_WEEK = 0.004 # offline-equivalent gain per week from the best alternative (label and data fixes)
SEED_NOISE = 0.002 # run-to-run spread of the offline score
weekly_gain = [0.020, 0.010, 0.006, 0.003, 0.0015, 0.001]
print("week offline gain expected online vs alternative above seed noise")
for week, gain in enumerate(weekly_gain, start=1):
online = gain * SHRINK
alt = ALT_GAIN_PER_WEEK * SHRINK
print(f"{week:>4} {gain:>12.4f} {online:>15.4f} {'keep tuning' if online > alt else 'switch':>14} {'yes' if gain > SEED_NOISE else 'no':>16}")
Output:
week offline gain expected online vs alternative above seed noise
1 0.0200 0.0100 keep tuning yes
2 0.0100 0.0050 keep tuning yes
3 0.0060 0.0030 keep tuning yes
4 0.0030 0.0015 switch yes
5 0.0015 0.0008 switch no
6 0.0010 0.0005 switch no
The first three weeks beat the alternative (0.010, 0.005 and 0.003 expected online vs 0.002 for the alternative per week), so tuning is the right use of time through week 3. In week 4 the expected online gain is 0.0015, below the alternative's 0.002, so you switch even though the offline number still rose. From week 5 the gains are also below the seed noise. I would stop after week 3 and move to label and data fixes, then revisit modelling with a fresh error analysis.
Where to put the effort instead
- Label audit and data fixes (often the biggest remaining lever).
- New features or fresher data sources.
- The decision layer: threshold, ranking cutoff, what action follows the score.
- Serving: latency, caching, monitoring, drift alerts.
- An online experiment to verify the current model before improving it further.
Trade-offs and pitfalls
- Sunk cost: "we are so close to the target" is not evidence; define the stop rule before you start the next block.
- Stopping too early on a model whose online link is strong is also a failure: if each offline point has repeatedly paid for itself, the rule above simply says continue.
- A precommitted time-box (for example two more weeks, then review) beats open-ended tuning, and the review should use online evidence.
Your team is deciding whether to build a capability in-house or buy or rent it from a vendor, for example a language model for customer support, an analytics platform, or a fraud-detection product. How do you decide, what are the visible and hidden costs, and what would change your recommendation?
Sample Answer
Direct answer
I would default to buying or renting when the capability is not what sets the company apart and volume is below the point where owning becomes cheaper; I would build when it is core to the product, when volume is high, or when data or regulation rules a vendor out; and I would consider a partnership in between. I decide with three tools together: a three-year total cost of ownership (TCO: every cost of the option over the period, not just the sticker price), a break-even volume (the monthly volume at which two options cost the same), and a weighted score on non-cost axes. For a language model for customer support at 30,000 conversations a month, my illustrative numbers favour buying, and the call flips if volume passes about 38,900 conversations a month or if strategic value is weighted heavily.
Visible and hidden costs
| Visible | Hidden | |
|---|---|---|
| Buy or rent | Licence or per-conversation fee, set-up fee | Integration work, vendor lock-in (becoming costly to leave) and exit cost, price rises at renewal, data egress (fees for moving your data out), your team's time running the vendor, quality you cannot tune, outage exposure under their service-level agreement (SLA) |
| Build | Engineer salaries, model and compute spend | Hiring time, evaluation and labelling, on-call and maintenance, security and compliance review, the features those engineers did not ship, key-person risk (the project stalls if one engineer leaves) |
Worked example: 3-year TCO (all figures illustrative)
Assume 30,000 conversations a month.
- Buy: $0.80 per conversation (36 months x 30,000 x $0.80 = $864,000), $60,000 integration once, and 0.5 of an engineer at $180,000 a year loaded (salary plus benefits and overhead) to run it ($90,000 a year, $270,000 over 3 years). Total $1,194,000. The vendor-operations engineer is costed at $180,000 and the build engineers at $200,000 because the run role is a more junior, partly shared position; that is a judgement, and on a common $200,000 basis the buy total is $1,224,000, buying is still about $178,000 cheaper, and break-even moves only slightly, to about 37,600 conversations a month ($880,000 / $23.40).
- Build on a hosted foundation-model API (a large pre-trained language model rented by the call from a provider, which you prompt, connect and evaluate rather than train from scratch): 3 engineers at $200,000 a year in year 1 ($600,000), 1.5 engineers for upkeep in years 2 and 3 ($300,000 a year), $40,000 evaluation and labelling, and $0.15 per conversation inference ($54,000 a year). Total $600,000 + $40,000 + $600,000 + $162,000 = $1,402,000.
At today's volume buying is about $208,000 cheaper over three years. Break-even volume V (conversations a month) comes from writing each three-year cost as a fixed part plus a part that grows with volume. Buying: fixed $60,000 integration + $270,000 to run the vendor = $330,000; per monthly conversation, $0.80 x 36 months = $28.80, so buying costs $330,000 + $28.80 x V. Building: fixed $600,000 + $40,000 + $600,000 = $1,240,000; per monthly conversation, $0.15 x 36 = $5.40, so building costs $1,240,000 + $5.40 x V. Setting them equal gives V = ($1,240,000 - $330,000) / ($28.80 - $5.40) = $910,000 / $23.40 = about 38,900 a month. Above that, building is cheaper. If the vendor raised its price to $1.00 per conversation, break-even would fall to about 29,700, below today's volume, so a vendor price rise is the biggest cost risk of buying.
Scored decision matrix (hypothetical scores, 1 to 5, where 5 is best for us)
Partner here means a co-development or managed-service arrangement, for example a vendor that tunes its model on our conversations under a shared roadmap and shared commercial terms. I have not costed it in the TCO because its terms vary widely, so its scores are a judgement between the two pure options until a quote exists.
| Axis | Weight | Build | Buy | Partner |
|---|---|---|---|---|
| 3-year cost | 30 | 2 | 4 | 3 |
| Time to value | 20 | 2 | 5 | 3 |
| Integration cost (5 = cheap to integrate) | 15 | 2 | 4 | 3 |
| Regulatory and data risk (5 = lowest risk) | 15 | 4 | 3 | 3 |
| Long-term strategic value | 20 | 5 | 2 | 4 |
| Weighted score | 100 | 2.90 | 3.65 | 3.20 |
Each score is multiplied by its weight and divided by 100. The reasons behind the scores, which are judgements to challenge: Build scores 2 on cost ($1.40M against $1.19M), 2 on time to value (hiring and building take months) and 2 on integration (we write every connection to our help desk and data systems ourselves), but 4 on regulatory and data risk (data never leaves our systems) and 5 on strategic value (we own the capability). Buy scores 4 on cost (cheapest at today's volume), 5 on time (live in weeks), 4 on integration (vendor connectors exist), 3 on regulatory and data risk (it depends on the vendor's terms) and 2 on strategic value (competitors can buy the same thing). Partner sits at 3 on most axes and 4 on strategic value because of the shared roadmap. Buy wins. If strategic value gets weight 40 and the others become 20, 15, 10 and 15, the scores become Build 3.50, Buy 3.20, Partner 3.40, and build wins. That shows the decision rests on one question: is this capability a source of lasting advantage for us?
My recommendation and what changes it
Buy now, on a contract with data-export rights and a price cap, and keep the conversation data and evaluation set in-house so a later switch to build costs weeks rather than a year. Revisit if volume nears 38,900 a month, if the vendor cannot meet data-residency (customer data must stay in a stated country or region) or audit requirements, if the vendor's price rises, or if the company decides this capability is its edge.
Pitfalls
- Comparing a vendor's price with only build salaries, ignoring maintenance, or the reverse.
- A weighted matrix hides disagreement about the weights, so I show the sensitivity to weights.
- Treating build as irreversible, or buy as free to leave.
Unlock Full Question Bank
Get access to all 17 Business Acumen and Commercial Context interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.