
Mobile App Crash-Free Metrics: Session Rate vs User Rate
When your dashboard shows a 99.5% crash-free rate, it's easy to feel confident about your mobile app's stability. But which crash-free metric are you actually looking at — session-based or user-based — and does it even matter? The answer is yes, it matters enormously, and choosing the wrong crash-free metrics for your reporting can mask serious reliability problems affecting your most valuable users. The distinction between session-based and user-based crash-free rates is one of the most overlooked yet consequential decisions in mobile observability, and getting it wrong can mean the difference between catching a revenue-critical bug early and finding out about it from one-star app store reviews three weeks later.
Why the Metric Definition Matters
Both session-based and user-based crash-free rates claim to measure the same thing — the percentage of "units" that don't experience a crash — but the "unit" changes everything. A session-based rate measures what percentage of app sessions are crash-free. A user-based rate measures what percentage of users never experience a crash during the reporting period. The formulas are straightforward:
Session-based crash-free rate:
Crash-Free Session Rate = (Total Sessions − Crashed Sessions) / Total Sessions × 100User-based crash-free rate:
Crash-Free User Rate = (Total Users − Users Who Crashed) / Total Users × 100For most apps, the session-based rate will always be higher — sometimes dramatically so. The reason is simple mathematics: a single user experiencing repeated crashes generates multiple crashed sessions, but only counts once in the user-based denominator. This isn't a bug in the calculation; it's a fundamental difference in what the two metrics are designed to surface.
Firebase Crashlytics reports both metrics in its dashboard, and the gap between them is often the most informative signal available. A narrow gap (less than 1-2 percentage points) typically indicates crashes are distributed evenly across your user base — likely environmental, device-specific, or edge-case issues. A wide gap (3+ percentage points) signals that a subset of users is experiencing crashes repeatedly, which almost always points to a deterministic bug tied to user state, account data, or a specific workflow path.
How Session-Based Rates Can Mislead
Consider a hypothetical but realistic scenario. Your app has 100,000 daily active users generating 500,000 sessions. On a given day, 500 sessions crash. That's a 99.9% session-based crash-free rate — stellar by any industry benchmark. The engineering team celebrates. The VP of Engineering reports the number to the board.
But what if those 500 crashed sessions belong to just 50 users? That means 50 users are crashing an average of 10 times each — they can't complete a single workflow without the app dying. The user-based crash-free rate in this scenario is 99.95% (49,950 crash-free users out of 50,000). Still looks fine. But those 50 users are almost certainly churning, leaving one-star reviews, and telling everyone they know that your app is "completely broken."
The problem compounds over longer time windows. A weekly or monthly session-based rate smooths out the spikes even further, while the user-based rate starts to reveal a clearer picture of how many real humans are actually affected. Apple's documentation on metric definitions emphasizes this distinction in its own App Store analytics, where crash data is reported per device (a user proxy) rather than per session for precisely this reason.
The Stakeholder Lens: Which Metric for Whom
Different stakeholders inside your organization need different crash-free metrics. Picking the right one for each audience prevents both false confidence and unnecessary alarm.
For executives and product leadership, user-based rates are almost always the right call. The business cares about how many customers are impacted, not how many individual sessions died. A board slide showing 99.9% session-based crash-free when 5% of paying users can't use a core feature is a governance failure waiting to happen. As BugsPulse's crash reporting platform emphasizes in its analytics philosophy, user-impact metrics align directly with revenue risk and churn probability.
For engineering teams, both metrics are essential but serve different debugging workflows. Session-based rates provide a high-signal early warning system: a sudden drop from 99.8% to 99.2% could mean a new crash in a frequently-visited screen affecting everyone equally. User-based rates, on the other hand, help you determine whether a crash is broad-but-shallow or deep-but-narrow — a distinction that completely changes your crash triage priority.
For QA and release management, session-based rates on a per-release basis are standard. Apple's App Store Connect and Google Play Console both report crash rates per app version using session-based calculations, making it the natural metric for deciding whether to halt a phased rollout or escalate a hotfix. However, Google's Android vitals documentation increasingly surfaces user-perceived crash rates alongside session-based ones, acknowledging that session-only views can obscure user-facing severity.
Calculating Both Metrics Across Platforms
Implementing both metrics in your own observability pipeline requires careful event attribution. Here's a simplified approach for both platforms using BugsPulse's event tracking:
import BugsPulse
// Track session start
BugsPulse.trackEvent("session_start", properties: [
"user_id": currentUser.id,
"session_id": UUID().uuidString,
"app_version": Bundle.main.appVersion
])
// Track crash event (called from crash handler/delegate)
BugsPulse.trackEvent("crash_occurred", properties: [
"user_id": currentUser.id,
"session_id": currentSessionId,
"crash_type": exception.type.description,
"stack_frames": exception.callStackSymbols.prefix(10).joined(separator: "\n")
])For Android, a similar pattern applies:
import com.bugspulse.android.BugsPulse
// Track session start
BugsPulse.trackEvent("session_start", mapOf(
"user_id" to currentUser.id,
"session_id" to UUID.randomUUID().toString(),
"app_version" to BuildConfig.VERSION_NAME
))
// Track crash event
BugsPulse.trackEvent("crash_occurred", mapOf(
"user_id" to currentUser.id,
"session_id" to currentSessionId,
"crash_type" to throwable.javaClass.simpleName,
"stack_frames" to throwable.stackTrace.take(10).joinToString("\n")
))With this event foundation, you can build dashboards that compute both rates. Using SQL-like aggregation on your analytics backend:
-- Session-based crash-free rate
SELECT
100.0 * (COUNT(DISTINCT session_id)
- COUNT(DISTINCT CASE WHEN event = 'crash_occurred' THEN session_id END))
/ COUNT(DISTINCT session_id) AS session_crash_free_pct
FROM events
WHERE date = CURRENT_DATE;
-- User-based crash-free rate
SELECT
100.0 * (COUNT(DISTINCT user_id)
- COUNT(DISTINCT CASE WHEN event = 'crash_occurred' THEN user_id END))
/ COUNT(DISTINCT user_id) AS user_crash_free_pct
FROM events
WHERE date = CURRENT_DATE;The gap between these two queries is your most actionable metric. A comprehensive crash observability approach should track both and alert on divergence.
Setting SLOs That Account for Both Metrics
Service Level Objectives (SLOs) for mobile reliability need to incorporate both user-based and session-based crash-free targets. A common mistake is setting a single SLO — say, "99.5% crash-free sessions" — and calling it done. This creates perverse incentives: if you only measure sessions, you might ignore a bug that crashes 1% of users 100% of the time, because it only impacts 0.2% of total sessions.
A more robust SLO framework looks like this:
crash_free_slos:
session_based:
target: 99.5%
window: 7d
severity: warning
user_based:
target: 99.0%
window: 7d
severity: critical
user_based_daily_active:
target: 99.5%
window: 1d
description: "DAU crash-free — catches acute regressions"
gap_threshold:
max_gap: 2.0 # percentage points
description: "Alerts if session rate exceeds user rate by >2pp"The gap threshold is particularly important. A widening divergence between session and user rates often signals the emergence of a state-dependent or account-specific crash — the hardest kind to catch in pre-release testing and the most damaging to user trust. Your crash budget enforcement should trigger an incident response when this gap exceeds your defined threshold, even if both individual metrics are still green.
The Reporting Cadence Problem
Another subtlety: the time window you choose dramatically changes which metric tells the more useful story. On a daily basis, user-based rates for apps with large user bases tend to be extremely high (99.9%+) because most users simply don't encounter the crash on any given day. This can create a false sense of security — the crash is still out there, accumulating impact on the users who do hit it, but the daily number never looks bad.
For daily operational monitoring, session-based rates provide better signal-to-noise for detecting new regressions quickly. For weekly and monthly business reviews, user-based rates tell the story that actually matters: how many of your customers had a bad experience this month? Industry benchmarks from 2026 suggest top-quartile apps maintain user-based crash-free rates above 99.7% on a 30-day rolling window, with session-based rates typically 0.3-0.8 points higher for the same period.
Building a Unified Dashboard
The ideal crash-free dashboard shows both metrics side by side, with trend lines and a divergence indicator. Here's what to include:
- Top-line KPIs: Both session-based and user-based crash-free rates, prominently displayed with 7-day trend arrows
- Divergence gauge: A simple visual showing the gap between the two rates, colored green (<1pp), yellow (1-2pp), or red (>2pp)
- Cohort breakdown: User-based rate segmented by app version, OS version, and device model
- User impact funnel: For any crash group, show how many unique users, how many total sessions, and the average crashes-per-affected-user
- Revenue-weighted rate: For apps with in-app purchases or subscriptions, a crash-free rate weighted by user LTV — your highest-value users experiencing crashes should trigger louder alarms
Tools like BugsPulse surface both metrics out of the box, along with automatic gap detection that alerts your team when the session-to-user rate divergence crosses your defined threshold. This prevents the "dashboard is green, but users are suffering" scenario that session-only monitoring creates.
The One Metric You Can't Skip
If your team can only track one crash-free metric, make it the user-based rate — but track it daily, not monthly. A daily user-based crash-free rate catches acute regressions affecting even a small fraction of users, while still aligning with the business question that actually matters: "How many of our users had a crash today?"
The session-based rate remains valuable as a secondary signal and a debugging tool, but it should never be the only number in your executive dashboard or your SLO compliance report. The gap between the two — that quiet divergence that session-only monitoring hides — is where your most damaging bugs live. Close that gap, and you'll have a crash-free metric framework that actually protects your users and your business.
Ready to track both session-based and user-based crash-free rates with automatic gap detection? app.bugspulse.com/register gives you both metrics, real-time divergence alerts, and revenue-weighted impact scoring — everything you need to stop relying on the wrong number.