Как посчитать crash-free users в SQL

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

Зачем crash-free

Crash-free users — главная stability метрика mobile. Если 99.5% юзеров не упало приложение, 0.5% — упало хотя бы раз. Industry-стандарт: 99.9% для consumer apps. Падение этой метрики после релиза = критическая регрессия, hotfix.

Формула

crash_free_users = (users_without_crash / total_active_users) × 100

В отличие от crash rate (events / total events), crash-free — на уровне юзеров. Один юзер с 10 crash = одна точка отказа.

Crash-free в SQL

WITH active_users AS (
    SELECT DISTINCT user_id
    FROM app_sessions
    WHERE session_date >= CURRENT_DATE - INTERVAL '7 days'
),
crashed_users AS (
    SELECT DISTINCT user_id
    FROM crash_events
    WHERE crash_date >= CURRENT_DATE - INTERVAL '7 days'
)
SELECT
    (SELECT COUNT(*) FROM active_users) AS active,
    (SELECT COUNT(*) FROM crashed_users) AS crashed,
    (1 - (SELECT COUNT(*) FROM crashed_users)::NUMERIC / NULLIF((SELECT COUNT(*) FROM active_users), 0)) * 100 AS crash_free_pct;

99.5%+ — хорошо. 99% — есть проблема. < 98% — большая часть юзеров видят crash.

По версии

После релиза мониторят на конкретной версии:

WITH crashed AS (
    SELECT DISTINCT user_id
    FROM crash_events
    WHERE crash_date >= CURRENT_DATE - INTERVAL '7 days'
)
SELECT
    s.app_version,
    s.platform,
    COUNT(DISTINCT s.user_id) AS active_users,
    COUNT(DISTINCT s.user_id) FILTER (WHERE c.user_id IS NOT NULL) AS crashed_users,
    (1 - COUNT(DISTINCT s.user_id) FILTER (WHERE c.user_id IS NOT NULL)::NUMERIC
     / NULLIF(COUNT(DISTINCT s.user_id), 0)) * 100 AS crash_free_pct
FROM app_sessions s
LEFT JOIN crashed c USING (user_id)
WHERE s.session_date >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY s.app_version, s.platform
ORDER BY s.app_version DESC, s.platform;

Падение CF от 99.9% (старая версия) до 98% (новая) — сигнал отката релиза.

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

Regression detection

WITH version_stats AS (
    SELECT
        app_version,
        platform,
        DATE_TRUNC('day', session_date)::DATE AS day,
        ROUND((1 - COUNT(DISTINCT user_id) FILTER (WHERE crashed)::NUMERIC
        / NULLIF(COUNT(DISTINCT user_id), 0)) * 100, 3) AS crash_free_pct
    FROM session_with_crash_flag
    WHERE session_date >= CURRENT_DATE - INTERVAL '14 days'
    GROUP BY app_version, platform, DATE_TRUNC('day', session_date)
)
SELECT
    app_version,
    platform,
    AVG(crash_free_pct) FILTER (WHERE day >= CURRENT_DATE - INTERVAL '3 days') AS recent_cf,
    AVG(crash_free_pct) FILTER (WHERE day < CURRENT_DATE - INTERVAL '3 days') AS baseline_cf,
    AVG(crash_free_pct) FILTER (WHERE day >= CURRENT_DATE - INTERVAL '3 days') -
    AVG(crash_free_pct) FILTER (WHERE day < CURRENT_DATE - INTERVAL '3 days') AS delta_pp
FROM version_stats
GROUP BY app_version, platform
HAVING ABS(
    AVG(crash_free_pct) FILTER (WHERE day >= CURRENT_DATE - INTERVAL '3 days') -
    AVG(crash_free_pct) FILTER (WHERE day < CURRENT_DATE - INTERVAL '3 days')
) > 0.5
ORDER BY delta_pp;

Версии с регрессией > 0.5pp — кандидаты на откат.

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

Ошибка 1. Crash rate вместо crash-free. Crash rate = events / events. Не учитывает многократные crashes у одного юзера.

Ошибка 2. Считать на all-time. Свежий релиз с CF 99% выглядит OK, если усреднить с двухнедельной историей. Считайте per day.

Ошибка 3. Игнорировать ANRs (Application Not Responding) на Android. ANR — не crash, но user experience такой же. Включайте в knowledge base.

Ошибка 4. Один CF на платформу. iOS vs Android имеют разную CF. Также OS version имеет значение (iOS 18 vs 17).

Ошибка 5. Не сегментировать на crash type. Native crash vs JS crash (для RN/Flutter) — разные fixing strategies.

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

FAQ

Какой CF хороший?

Consumer apps: 99.9%+. Games: 99.5%+. Enterprise: 99.95%.

CF включает background crashes?

По вкусу. Foreground важнее (юзер видит). Background = ANR.

Crash-free sessions vs users?

User — строже (один user с many crashes считается раз). Session — больше total volume.

Когда rollback?

CF падение > 1pp или абсолютно < 99% — стоит откатываться.

Тулинг?

Crashlytics, Bugsnag — стандарт. В SQL — для собственных пайплайнов.