Как посчитать involuntary churn в SQL

Закрепи формулу involuntary churn в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать involuntary churn в Telegram

Зачем разделять

Voluntary churn = customer сам cancel, не оправдал ожиданий. Involuntary churn = система cancel из-за failed payment (expired card, insufficient funds). Лечится разными способами: voluntary — продукт, involuntary — dunning + payment infra. Без разделения непонятно, куда вкладываться.

Voluntary vs involuntary

В таблице subscriptions обычно есть cancellation_reason:

  • user_cancel — voluntary
  • payment_failed — involuntary
  • expired_grace — involuntary
  • chargeback — involuntary

Involuntary в SQL

SELECT
    COUNT(*) FILTER (WHERE cancellation_reason IN ('payment_failed', 'expired_grace', 'chargeback')) AS involuntary,
    COUNT(*) FILTER (WHERE cancellation_reason = 'user_cancel') AS voluntary,
    COUNT(*) AS total_churn
FROM subscriptions
WHERE churned_at BETWEEN '2026-04-01' AND '2026-04-30';

Доля от total churn

WITH stats AS (
    SELECT
        COUNT(*) FILTER (WHERE cancellation_reason IN ('payment_failed', 'expired_grace', 'chargeback')) AS involuntary,
        COUNT(*) AS total
    FROM subscriptions
    WHERE churned_at >= CURRENT_DATE - INTERVAL '90 days'
)
SELECT
    involuntary,
    total,
    involuntary::NUMERIC * 100 / NULLIF(total, 0) AS involuntary_pct
FROM stats;

В индустрии involuntary обычно 20-40% от total churn. Меньше = хороший dunning.

Закрепи формулу involuntary churn в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать involuntary churn в Telegram

По причине

SELECT
    cancellation_reason,
    COUNT(*) AS churns,
    SUM(mrr) AS lost_mrr,
    COUNT(*) * 100.0 / SUM(COUNT(*)) OVER () AS pct
FROM subscriptions
WHERE churned_at >= CURRENT_DATE - INTERVAL '90 days'
  AND cancellation_reason IN ('payment_failed', 'expired_grace', 'chargeback', 'user_cancel')
GROUP BY cancellation_reason
ORDER BY churns DESC;

Топ-причина involuntary часто — expired_grace. Решается через update-card flow и smart retries.

Частые ошибки

Ошибка 1. Все churn как один. Без сегментации не понять, что лечить. Voluntary — продукт. Involuntary — billing.

Ошибка 2. Считать involuntary как «потерянных». 30-60% involuntary можно вернуть через dunning. Не списывайте сразу.

Ошибка 3. Не учитывать chargeback fees. Каждый chargeback дополнительно стоит $15-25. Учитывайте в lost revenue.

Ошибка 4. Все expired_grace как involuntary. Иногда юзер не обновил карту намеренно — это voluntary с маской involuntary. Сложно отделить.

Ошибка 5. Один dunning policy для всех сегментов. Enterprise — phone call. SMB — email + retry. SMB-эффективные методы не работают для enterprise и наоборот.

Связанные темы

FAQ

Какой involuntary normal?

20-40% от total churn для B2C. 5-15% для B2B Enterprise (annual contracts).

Как уменьшить?

Smart dunning, card updater services (Stripe), pre-expiry email-cards.

Involuntary считается в churn rate?

Обычно да. Некоторые компании отдельно «net churn excluding involuntary».

Card updater стоит подключать?

Stripe Card Account Updater — $0.25/match. Окупается для customers с высоким LTV.

Как повысить recovery rate?

A/B test разных dunning sequences. Можно поднять recovery с 30% до 60%.