◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/Dev Tools
⬡ Dev Tools/2026-05-19Advanced

Auto-Throttling AdMob When Crash Rates Spike: A Revenue-Protecting Brake Architecture with Rork, Firebase Remote Config, and Crashlytics

When crash rates spike, do you keep showing ads and watch your store rating crater, or pull back and accept the lost revenue? After 12 years of indie operations, my answer is neither: a four-state auto-throttle architecture that ties Firebase Remote Config and Crashlytics signals into AdMob serving decisions.

Rork585AdMob73Firebase Remote ConfigCrashlytics12Architecture22Long-term Operations4Indie Developer11

✦ Premium Article

In spring 2024, one of the wallpaper apps I run watched its crash rate jump from 0.3% to 4.8% within hours of a minor iOS 18 update. The technical culprit turned out to be a CADisplayLink behavior change, but the part I regret most is something else: for the twelve hours it took me to notice, my app kept happily serving AdMob interstitials. Twenty-seven reviews piled up saying "it crashes the moment an ad appears." The average rating dropped from 4.5 to 4.1, and over the following weeks organic installs fell 32%. The ad revenue I earned during those twelve hours was dwarfed many times over by what I lost afterward.

I'm Masaki Hirokawa, an artist-creator who has been building personal apps since 2014. My catalog has crossed 50 million cumulative downloads, and once AdMob revenue passed the threshold of seven figures (in Japanese yen) per month, I started treating revenue and stability as something that belongs on the same dashboard. This article walks through the four-layer architecture I now use to detect rising crash rates and automatically dial back AdMob serving — and, just as importantly, how to dial it back up safely.

Why Tie Ads and Stability into a Single Architecture

The Google Mobile Ads SDK initialization is heavier on the process startup path than most documentation suggests. From AdMob SDK v11 onwards, parallel initialization and cold-start improvements have helped, but in my measurements the AdMob-related class loading still accounts for 8 to 14 percent of cold-start time, and once you layer mediation SDKs (AppLovin, Meta Audience Network, and so on) it can exceed 20 percent. When a crash spike hits, you don't just have an app problem; you potentially have ad-SDK-driven crashes (WebKit process OOM, mediation bid-request cascades) muddying the diagnostic signal.

Wiring "if crash rate exceeds X, throttle ad serving in stages" into the runtime gives you three things at once. First, it physically stops the bleeding. Second, it removes ad-SDK-related crashes from the Crashlytics noise floor while you triage. Third — and this is the one that compounds — it prevents users from establishing the association "ads here mean crashes." That association persists in reviews for years.

Architectural Overview — Four Layers with Distinct Responsibilities

The system breaks cleanly into four layers, each independently safe-failable.

  1. Observation layer: Firebase Crashlytics plus custom telemetry, collecting crash and error signals in real time
  2. Decision layer: Cloud Functions (or Cloudflare Workers) aggregating the data into three rolling windows and choosing a state
  3. Distribution layer: Firebase Remote Config delivering the chosen ad_throttle_state to clients
  4. Execution layer: A client-side AdServingGate that translates state into actual load/show decisions

The layering matters most when you're recovering from an incident at 3 a.m. The last-resort safety nets are: manually rewrite Remote Config to Normal, then the distribution kill switch, then the client fallback default. Each layer can fail safe on its own. Knowing that lets you sleep.

State Model: Normal, Caution, Throttle, Halt

In my production apps, the four states are tuned as follows:

  • Normal: Crash-free rate ≥ 99.7%. All ad units serve normally.
  • Caution: Crash-free rate between 99.0% and 99.69%. Interstitial frequency cut to 50%; rewarded ads continue.
  • Throttle: Crash-free rate between 96.0% and 98.99%. Interstitials disabled; banners only; rewarded ads served only on explicit user action.
  • Halt: Crash-free rate below 96.0%, or more than 20 crashes per minute. All ad loading stops; SDK initialization is skipped.

The four-state granularity is what lets you preserve revenue even when the system misfires. In one of my apps, a 6-hour Throttle held revenue at 24% of normal during that window — but the upstream Caution period kept revenue at 72% of normal before things deteriorated. The all-or-nothing version of this system would have run me to zero.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Three-tier rolling-window monitoring (1-minute / 10-minute / 60-minute) with concrete thresholds that suppress false triggers
✦A four-state phase-out (Normal / Caution / Throttle / Halt) delivered through Firebase Remote Config, with full implementation code
✦A recovery playbook covering hysteresis, smoke tests, and manual overrides — preserving 72% of AdMob revenue while restoring stability
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ Dev Tools2026-05-19
Rolling Out Firebase App Check in Rork Without Breaking AdMob or Crashlytics
A practical, staged rollout for Firebase App Check in Rork apps that keeps Crashlytics reporting, Realtime Database listeners, and AdMob payouts intact — written from running AdMob-funded indie apps in production.
⬡ Dev Tools2026-08-01
Every Experiment Kept Landing on the Same Devices: Hash Choice and Salt Position, Measured Across a Million IDs
On-device experiment assignment looked fine in isolation, then collapsed the moment two experiments ran side by side. Here is what one million IDs revealed about four hash functions, why the culprit was the concatenation order rather than hash quality, and the implementation I settled on, with the measured numbers.
⬡ Dev Tools2026-07-27
When to Raise Your Minimum iOS Version — Count Leftover Branches, Not User Percentages
Judging a minimum OS bump by usage share produces the same answer every year, so the decision never happens. Here is the annotation convention, the sweep script that counts how many iOS and Android branches each candidate floor would retire, and what to watch for 30 days after.