All writing
Quality·7 min read·Mar 2026

Why crash rate is a monetization metric

ANRs and crashes silently tank ad revenue. Here's the math.

By Priya Natarajan

Glowing red error stack trace on a dark surface

When a session ends in a crash, you lose more than the user's trust. You lose every impression that would have rendered in the rest of that session, every postback that would have fired on its close, and a meaningful slice of next-day retention. The math is uncomfortable.

The chain of losses

Average session length for a healthy mobile app is 6–9 minutes. Average impressions per session, after caps, is 2.4. A session that crashes at minute two has lost roughly 1.6 impressions on average — gone, unrecoverable.

Compound that across a 1% crash rate and 5M DAU and you are looking at 80,000 lost impressions per day. At a $7 eCPM that is $560 of revenue, every day, attributable to a single percentage point of stability.

The full revenue-loss model

The formula is short: lost revenue per day equals DAU × crash rate × (impressions per session – impressions before crash) × eCPM / 1000. The intuition gets uncomfortable when you plug in realistic numbers.

  • 1M DAU × 1.5% crash × 1.6 lost impressions × $6 eCPM ≈ $144/day, $52k/year
  • 5M DAU × 1.0% crash × 1.6 lost impressions × $7 eCPM ≈ $560/day, $204k/year
  • 25M DAU × 0.6% crash × 1.6 lost impressions × $8 eCPM ≈ $1,920/day, $700k/year
  • And these numbers only count the lost impressions — they ignore the retention drag, which is usually larger

ANRs are crashes that monetize even worse

An ANR (Application Not Responding) on Android is the silent killer. The user sees a frozen UI, force-quits, and uninstalls — but no crash report fires, so the team that watches Crashlytics never sees it. ANRs above 0.5% are common in apps that initialise their ad SDK on the main thread.

The iOS equivalent is the watchdog termination — a 0x8badf00d exit code, generally caused by the same root cause: synchronous work on the main thread during launch. Treat both the same way you treat crashes: alert on them, model the revenue loss the same way, and gate them on every release.

Platform-specific defensive patterns

These are the patterns we ship as defaults in every Apps Kit SDK integration. None are clever. All are missing from the average codebase we audit.

  • Android: initialise the SDK from a WorkManager task, not Application.onCreate
  • Android: hold ad views in WeakReference and null them in onDestroyView
  • iOS: dispatch SDK init onto a utility QoS queue from didFinishLaunching, never block
  • iOS: invalidate ad delegates and break retain cycles in viewWillDisappear, not deinit
  • Both: gate every ad request behind a state machine that knows consent, network, and SDK-ready status

Where the crashes come from

  • SDK initialisation on the main thread — the single most common cause we see
  • Synchronous ad loading in onCreate / didFinishLaunching
  • Memory pressure from holding ad views beyond their useful life
  • Race conditions between consent state and ad request

Alerting on revenue-relevant crashes

Crash rate alerts are usually wired to a fixed percentage threshold and ignored when they go off. Wire them to revenue impact instead — alert when the modelled daily revenue loss from a crash signature crosses $X — and the alert becomes one that the on-call engineer is willing to wake up for. We ship a Cloud Function template that does exactly this against the BigQuery export.

The defensive pattern

Initialise the SDK on a background dispatcher, gate every ad request behind a consent state machine, and release ad view references the moment the placement is dismissed. None of this is novel. All of it is missing from the average integration we audit.

Treat crash rate as a revenue lever, not an engineering hygiene metric, and the conversation about prioritising stability work gets a lot shorter.

What to do this week

Pull your crash dashboard, multiply the top three crash signatures by the model above, and put a dollar figure next to each. The release that fixes the biggest one will pay for itself before the next App Store review window closes.