Как считать LTV в SaaS: разбор формул и где в них дыры
LTV (lifetime value) — одна из тех метрик, которую все знают по названию, и почти все считают неправильно. Я регулярно вижу слайды с «LTV = $1200, CAC = $300, всё отлично, гоним», после которых выясняется, что LTV посчитан по упрощённой формуле, валидной только для гипотетического стационарного бизнеса. У реальной SaaS-компании эта цифра в 1.5–3 раза меньше.
Расскажу, какие формулы LTV существуют, когда какую применять, и где в каждой дыры. Без матанализа, но с конкретными примерами на цифрах.
Самая простая формула
ltv = arpu / churn_rateЭту формулу учат на бизнес-курсах. ARPU — средний доход с пользователя в месяц. Churn rate — месячный churn в процентах. Деление даёт «среднее время жизни клиента, умноженное на ARPU».
На цифрах: ARPU = $50, monthly churn = 5%. LTV = 50 / 0.05 = $1000.
Где дыра. Эта формула верна только при допущении, что и ARPU, и churn rate стабильны во времени. На реальном SaaS они нестабильны:
- Churn почти всегда выше у новых пользователей и снижается с возрастом когорты. Это U-shape или L-shape кривая.
- ARPU растёт за счёт upsell и снижается за счёт downgrade.
- Новые когорты ведут себя иначе, чем старые: продукт меняется, аудитория меняется.
Если в твоём продукте 50% новых пользователей уходят в первый месяц, а потом churn ровно 2% — простая формула даст $1000, реальный LTV будет $400.
Формула с учётом маржинальности
ltv = (arpu * gross_margin) / churn_rate$50 ARPU не значат $50 в карман компании. Из них вычитаются costs of revenue: хостинг, поддержка, payment processing. Если gross margin = 70%, то реальный LTV = 50 * 0.7 / 0.05 = $700.
Эта поправка обязательна для любого расчёта LTV/CAC. Без неё ratio врёт в полтора раза — что критично, когда ты на основании этой цифры принимаешь решение о масштабировании маркетинга.
В B2C SaaS gross margin обычно 75–85%. В B2B с serious enterprise-поддержкой — 50–70%. В marketplace с физической логистикой — 20–40%.
Когортный LTV
Самая честная формула — посчитать LTV прямо по когортам, без обобщающих допущений.
WITH cohort_revenue AS (
SELECT
date_trunc('month', u.signup_date)::date AS cohort_month,
date_trunc('month', s.payment_date)::date AS revenue_month,
SUM(s.amount * 0.7) AS gross_profit -- если хочется LTV с маржой
FROM users u
LEFT JOIN subscriptions s ON s.user_id = u.id
GROUP BY 1, 2
),
cohort_size AS (
SELECT
date_trunc('month', signup_date)::date AS cohort_month,
COUNT(*) AS users
FROM users
GROUP BY 1
)
SELECT
cr.cohort_month,
cs.users,
SUM(cr.gross_profit) AS total_gross_profit,
SUM(cr.gross_profit) / cs.users AS gross_profit_per_user
FROM cohort_revenue cr
JOIN cohort_size cs USING (cohort_month)
GROUP BY cr.cohort_month, cs.users
ORDER BY cr.cohort_month;Получаешь по каждой когорте суммарный gross profit на пользователя. Это и есть LTV — но только для тех когорт, которые уже «дожили» до своего настоящего LTV.
Главная ловушка: данные обрезаются
Если когорта зарегистрировалась год назад, и в среднем клиент живёт 3 года, ты видишь только треть LTV. Все когорты младше 3 лет показывают заниженное число. Если ты возьмёшь среднее по всем когортам и назовёшь это LTV — получишь искажённую цифру.
Способов решить два.
Только зрелые когорты
Берёшь только когорты старше N месяцев, где N — медиана lifetime по историческим данным. Например, последние 36 когорт исключаешь, считаешь LTV только по тем, что 3+ года живут. Минус — данные старые, могут не отражать текущий продукт.
Прогнозный LTV
Строишь survival curve на исторических данных, экстраполируешь на будущее. Базовый подход — Kaplan-Meier estimator или фиттинг экспоненциальной модели:
import pandas as pd
from lifelines import KaplanMeierFitter
users = pd.read_parquet('users_with_churn.parquet')
kmf = KaplanMeierFitter()
kmf.fit(
durations=users['lifetime_months'],
event_observed=users['churned'],
)
# Survival на 60 месяцах
survival_60m = kmf.survival_function_at_times(60).values[0]
print(f'Probability of being active at 60 months: {survival_60m:.2%}')
# LTV: интеграл от ARPU * S(t) по времени
arpu_per_month = 50 * 0.7 # с маржой
ltv_60m_horizon = arpu_per_month * kmf.survival_function_.cumsum().iloc[-1]
print(f'LTV (60-month horizon): ${ltv_60m_horizon:.0f}')Плюс — учитывает реальное поведение когорт. Минус — экстраполяция на горизонт, который ты не видел.
На моей практике компромисс — считать LTV на горизонте 36 месяцев. Дольше — слишком много допущений. Короче — слишком мало времени, чтобы увидеть зрелое поведение пользователя.
LTV для разных сегментов
Среднее по компании LTV — почти бесполезная цифра. SMB-клиенты живут 6 месяцев со средним чеком $30. Enterprise — 4 года со средним чеком $5000. Среднее покажет «$800», и оно не отражает ни тех, ни других.
Резать LTV нужно как минимум по:
- Плану/тарифу.
- Источнику привлечения (organic / paid / referral).
- Размеру клиента (для B2B — по числу seats или ARR-band).
- Гео — особенно если есть валютные различия.
Только в этих разрезах LTV становится цифрой, на которую можно опираться при принятии решений.
Куда деть recurring upgrades
Часть пользователей с временем переходит на более дорогой план. Это улучшает LTV, и его надо учитывать. Но не двойным счётом.
Простой подход — считать monthly_revenue_per_user отдельно для каждого месяца жизни когорты:
SELECT
cohort_month,
months_since_signup,
SUM(monthly_revenue) / cohort_size AS arpu_at_month
FROM ...
GROUP BY 1, 2;Получаешь ARPU как функцию возраста когорты. Если в N+12 месяцев ARPU выше, чем в N+1 — это net dollar expansion, и он повышает LTV. Простая формула ARPU / churn этого вообще не учитывает.
Связь с CAC
LTV сам по себе не имеет смысла. Имеет смысл только LTV/CAC. Базовый бенчмарк для SaaS — LTV/CAC ≥ 3.
Но и CAC надо считать честно. Чаще всего CAC — это «суммарный маркетинговый бюджет, делённый на количество новых клиентов». Неправильно: внутри суммарного бюджета сидят затраты на awareness, retargeting, удержание существующих клиентов. И часть «новых» клиентов пришла без маркетинга, по рекомендации.
Чистый CAC — это Direct CAC, посчитанный только по платному трафику с прозрачным attribution. Organic-клиентов в CAC включать нельзя, иначе ты «удешевляешь» цифру и получаешь нереалистичный LTV/CAC.
Чек-лист перед презентацией LTV
- Учтена ли маржинальность? Если нет — цифра завышена в 1.3–2 раза.
- Какой горизонт? «Бессрочный» LTV — это
ARPU/churn, и он почти всегда оптимистичен. - Резка по сегментам? Среднее без сегментации обычно бесполезно.
- Включает ли upsell/downgrade? Если нет — недооценка для зрелых SaaS.
- На каких когортах посчитано? Только зрелых или со всеми (с искажением)?
- Какой CAC рядом? Direct или Total? Включает ли organic?
Если хотя бы три пункта не выдержаны — цифра LTV не годится для принятия решений о масштабировании. Можно показывать как ориентир, но не как обоснование.
Что забрать с собой
Простая формула ARPU / churn хороша как ментальный ориентир, но плохо работает на реальных данных. Когортный LTV с учётом маржи — это минимум для бизнес-решений. Прогнозный LTV с survival analysis — для продвинутых случаев. Любой LTV без сегментации и без рядом стоящего честного CAC — иллюстрация, не метрика.
Дальше копать стоит в сторону probabilistic LTV (BG/NBD models для contractual settings, Pareto/NBD для non-contractual), и в сторону связи LTV с unit economics: payback period, contribution margin per cohort. Эти штуки отвечают на вопросы, которые годовая LTV-цифра не закрывает.