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

Проверь себя · 1/3разбор после ответа
В таблице events(user_id, created_at) поле created_at имеет тип отметки времени с долями секунд. Как корректно посчитать количество событий по дням?

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

Voluntary churn — это когда пользователь сам отменяет подписку: продукт не оправдал ожиданий. Involuntary churn — когда подписку отменяет система из-за неудавшегося платежа (просроченная карта, нехватка средств). Лечатся они по-разному: voluntary — это работа над продуктом, involuntary — dunning и платёжная инфраструктура. Без разделения непонятно, куда вкладываться.

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';

Доля от всего 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% от всего 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. Лечится через сценарий обновления карты и умные повторные списания.

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

Ошибка 1. Считать весь churn одинаковым. Без сегментации не понять, что лечить: voluntary — это про продукт, involuntary — про биллинг.

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

Ошибка 3. Не учитывать комиссии за chargeback. Каждый chargeback дополнительно стоит $15-25. Закладывайте это в потерянную выручку.

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

Ошибка 5. Единый dunning для всех сегментов. Для enterprise работает звонок, для SMB — письмо плюс повторное списание. Методы, эффективные для SMB, не работают для enterprise, и наоборот.

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

FAQ

Какой involuntary считается нормальным?

Для B2C нормой считаются 20-40% от всего churn. Для B2B Enterprise доля ниже — 5-15%, потому что там годовые контракты и меньше провалов регулярных списаний.

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

Настройте умный dunning и подключите сервисы автообновления карт (например, у Stripe). Помогают и письма-напоминания об обновлении карты ещё до того, как она истечёт.

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

Обычно да, involuntary входит в общий churn rate. Но некоторые компании считают отдельную метрику net churn без involuntary, чтобы отделить продуктовый отток от платёжного.

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

Да, если у вас есть пользователи с высоким LTV. Stripe Card Account Updater стоит $0.25 за совпадение и окупается за счёт удержанных подписок дорогих клиентов.

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

Тестируйте через A/B-тесты разные цепочки dunning — тайминги писем, число попыток списания, тон сообщений. Так recovery rate реально поднять с 30% до 60%.