The CAC:LTV ratio is a common unit economics metric in SaaS. Yet most founders calculate LTV as "average revenue per customer times average lifespan" -- a formula that treats every customer as identical. Some customers pay for years. Others already placed their last payment and you do not know it yet. This analysis uses probabilistic modeling to predict what each individual customer is worth, which ones are still active, and where to focus your retention spend.
Worked Example (Simulated)
Made-up data, seed 17. A script builds the customers and payments below. They are not real SaaS data.
Question: How well can a simple model guess payment count for the next 90 days from the past 180 days?
Inputs: 120 customers, 180 days of past payments, and 90 days held back for a test. Each customer's payment rate is drawn from a gamma distribution, so rates are uneven by design. Payment amounts are drawn uniformly from $20 to $120, so the mean of $69.55 is near the built-in 70. The past span has 1082 payments.
Method: For each customer, the model guesses a payment count for the test span. It adds 1 to past payments, multiplies by 90, and divides by 180. The added 1 is a simple way to smooth the rate. The script groups customers by past payment count and compares the guess with the test count. For a rough value, it multiplies the mean payment by the mean guessed count.
import numpy as np
SEED = 17
rng = np.random.default_rng(SEED)
customers = 120
calibration_days = 180
holdout_days = 90
# Simulated repeat-payment data. Each customer has a different payment rate.
rate_per_day = rng.gamma(shape=2.0, scale=0.025, size=customers)
calibration_counts = rng.poisson(rate_per_day * calibration_days)
holdout_counts = rng.poisson(rate_per_day * holdout_days)
width = max(calibration_counts.max(), 1)
values = rng.uniform(20.0, 120.0, size=(customers, width))
revenue = sum(values[i, :calibration_counts[i]].sum() for i in range(customers))
transactions = int(calibration_counts.sum())
mean_order_value = revenue / transactions
# Simple smoothed rate: add one prior payment in each 180-day calibration span.
predicted = (calibration_counts + 1) * (holdout_days / calibration_days)
print(f"Simulated data, seed {SEED}")
print(f"Inputs: {customers} customers; {calibration_days}-day calibration; "
f"{holdout_days}-day holdout")
print(f"Calibration: {transactions} payments; "
f"mean order value ${mean_order_value:.2f}")
print("Method: predicted holdout payments = "
"(calibration payments + 1) x holdout days / calibration days")
print("Holdout check by calibration payment count:")
for label, mask in [
("0", calibration_counts == 0),
("1-3", (calibration_counts >= 1) & (calibration_counts <= 3)),
("4+", calibration_counts >= 4),
]:
n = int(mask.sum())
pred = float(predicted[mask].sum())
actual = int(holdout_counts[mask].sum())
print(f" {label} payments: {n} customers; "
f"predicted {pred:.1f}; actual {actual}")
print(f"All customers: predicted {predicted.sum():.1f} holdout payments; "
f"actual {holdout_counts.sum()}")
mae = np.abs(predicted - holdout_counts).mean()
print(f"Mean absolute error per customer: {mae:.2f} payments")
print(f"Illustrative mean future value per customer: "
f"${predicted.mean() * mean_order_value:.2f}")
Printed output:
Simulated data, seed 17
Inputs: 120 customers; 180-day calibration; 90-day holdout
Calibration: 1082 payments; mean order value $69.55
Method: predicted holdout payments = (calibration payments + 1) x holdout days / calibration days
Holdout check by calibration payment count:
0 payments: 4 customers; predicted 2.0; actual 4
1-3 payments: 23 customers; predicted 36.0; actual 52
4+ payments: 93 customers; predicted 563.0; actual 506
All customers: predicted 601.0 holdout payments; actual 562
Mean absolute error per customer: 2.16 payments
Illustrative mean future value per customer: $348.32
Result: The model guesses 601.0 payments for all customers. The test has 562. The added 1 raises every customer's guess by half a payment, 60 payments over 120 customers, which is more than the 39 payment gap between 601.0 and 562. The mean absolute error, the average size of the miss, is 2.16 payments per customer. The rule over-predicts the group with 4 or more past payments (563.0 guessed, 506 in the test) and under-predicts the group with 0 past payments (2.0 guessed, 4 in the test) and the group with 1 to 3 (36.0 guessed, 52 in the test). The rough mean future value is $348.32 per customer.
Limit: This is a small test with made-up data. It checks a simple rate rule, not the BG/NBD model. The value guess assumes future payments have the same mean value as past ones. It does not show profit, churn, or fit for a real SaaS firm.
Sources
- Fader P, Hardie B, Lee K (2005), "Counting your customers" the easy way. Cited only for who published the BG/NBD model, and when.
- Schmittlein D, Morrison D, Colombo R (1987), Counting your customers: who are they and what will they do next? Cited only for who published that model, and when.
Why the Simple LTV Formula Fails
The back-of-napkin formula -- ARPU divided by churn rate -- gives you a single number for your entire business. If your ARPU is $80/month and monthly churn is 4%, you get LTV = $80 / 0.04 = $2,000. That number is fine for a pitch deck. It is useless for deciding which customers to invest in.
To forecast what your own customers are worth from here, straight from a transaction file, try the free customer lifetime value tool.
The problem is variation. Your $2,000 average hides a customer who pays $199/month and has been active for 2 years (actual value: $4,776 and counting) and a customer who paid $29 once and vanished (actual value: $29). Treating them the same leads to blanket retention campaigns that overspend on low-value accounts and underspend on high-value ones.
A single LTV figure that is an average hides customer-level variation. Per-customer predictions can show whether your best accounts justify more acquisition spend and whether your lowest-value accounts are worth retaining.
How Per-Customer CLV Prediction Works
The worked example above uses a simple rate rule, not BG/NBD (Beta-Geometric / Negative Binomial Distribution). BG/NBD was published by Fader, Hardie and Lee in 2005. The idea behind this kind of model is simple even if the math is not: it looks at each customer's purchase history and estimates two things.
First, is the customer still "alive"? Not in the literal sense, but in the buying sense -- are they still in their purchasing cycle, or have they silently churned? A customer who bought 5 times last month is almost certainly alive. A customer who bought 5 times over 3 years and has not returned in 6 months is probably gone. The model quantifies this as a P(alive) score between 0 and 1.
Second, how many future transactions should you expect? The model weighs recency (when did they last pay?) against frequency (how often do they pay?) to predict future behavior. A second step estimates the average value of each customer's transactions. Multiply expected future transactions by expected order value, and you get a predicted CLV for every person in your database.
The result is not one LTV number for the business. It is a ranked list of every customer with their individual predicted value, their probability of still being active, and their expected future transactions over the next 12 months.
What the Report Shows You
P(alive) probability matrix -- arguably the most actionable output. A heatmap showing which frequency-recency combinations correspond to active customers and which correspond to likely churners. Scores in the middle of the range mark customers who may be worth a check-in; test it before you set a rule.
Top customers by predicted CLV -- a ranked list of your highest-value accounts by predicted future revenue. Each entry shows the customer identifier, predicted CLV, P(alive) score, and historical purchase stats. This is the list your retention team should work from. Losing any of these customers has an outsized impact on future revenue.
CLV distribution -- shows how predicted value is distributed across your customer base. In most businesses, the distribution is heavily right-skewed. The chart shows how concentrated your value is and can help you decide how many customers are worth individual attention versus segment-level campaigns.
Customer segment summary -- groups customers into actionable categories based on model scores: Champions (high frequency, high recency, high CLV), At Risk (historically valuable but declining P(alive)), Hibernating (low recent activity), and New (recent first purchase, not enough data yet). Each segment shows size, average CLV, average P(alive), and total predicted revenue. Design a different retention action for each segment.
Expected transactions matrix -- a heatmap showing expected future transactions by frequency and recency. Customers in the upper-right (high frequency, recent purchase) are expected to keep buying. Customers in the lower-left are expected to buy rarely or never.
Holdout check -- the data is split into a calibration period and a holdout period. The holdout table shows predicted vs. actual transactions for each frequency group. When they track closely, the forward-looking estimates have more support.
When to Use CLV Modeling
- Setting acquisition budgets -- If you cap CAC at one third of CLV, a CLV of $3,200 allows a CAC of about $1,067. The target is your choice; margin and payback time also matter. A per-customer model can show this for each segment, not just the average.
- Prioritizing retention spend -- instead of blanket discounts to everyone, invest in high-CLV customers showing declining P(alive). A personalized check-in for a customer worth $8,000 is a better use of CS time than a mass email to $200 accounts.
- Investor and board reporting -- "our average LTV is $2,000" is a claim. a statement about predicted value and the chance a group is still active is more specific. The per-customer model gives your unit economics presentation substance.
- Customer segmentation for marketing -- the segment summary directly maps to marketing actions: win-back campaigns for At Risk, loyalty programs for Champions, activation sequences for New, and resource reallocation away from Hibernating.
- Pricing decisions -- compare CLV across plan tiers. If Enterprise customers have 4x the CLV of Pro customers, investing in enterprise sales capacity has a quantifiable return.
What Data Do You Need?
A CSV of your transaction or billing history with three required columns:
Required columns
- Customer ID -- email, account ID, or any unique identifier
- Transaction date -- payment date, invoice date, or renewal date
- Order value -- payment amount in dollars (not cents)
Optional columns
- Order ID -- helps deduplicate multi-line exports (common with Shopify)
- Order status -- filters out refunded or canceled transactions
For SaaS, each monthly subscription payment is a transaction row. If your billing system only records subscription start/end dates (not individual payments), generate a row per payment month before uploading.
Minimum: 50 unique customers with some repeat transactions and at least 90 days of history. Best results with 200+ customers and 6+ months. The model needs repeat purchase behavior -- datasets with mostly one-time buyers produce estimates with high uncertainty.
Common Mistakes
- Using the simple formula when you need per-customer predictions. ARPU / churn rate gives you one number. If you are making decisions about individual accounts -- who to call, who to discount, who to let go -- you need per-customer CLV.
- Too little history. With less than 90 days of data, everyone looks "alive" because nobody has had time to churn. The model runs but predictions are unreliable. Six months is the sweet spot.
- Duplicate transaction rows. If your export has one row per line item rather than one row per order, frequencies are inflated. Use the order ID column to let the tool deduplicate.
- Ignoring seasonality. The BG/NBD model assumes roughly stationary purchase rates. If 80% of your revenue comes in Q4, predictions based on off-season data will underestimate value. Note this when interpreting results from seasonal businesses.
When to Use Something Else
- Want retention trends across signup cohorts: Use cohort retention analysis -- it shows whether newer customers retain better than older ones. Use cohorts for the big picture, CLV for individual targeting.
- Want to identify at-risk subscriptions right now: Use churn prediction -- it works from subscription status data and gives you an immediate at-risk list. CLV predicts long-term value; churn prediction flags short-term risk.
- Want simple customer segmentation without probabilistic modeling: Use RFM segmentation -- it groups customers by recency, frequency, and monetary value without the full BG/NBD model. Good for quick targeting, but descriptive rather than predictive.
- Have contractual subscriptions with known end dates: If customers have fixed-term contracts (annual SaaS licenses), the BG/NBD model's silent-churn assumption does not apply. Use survival analysis instead.
Your turn
Bring your own data and the question you actually need answered.
MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai