Crash Reporting and App Stability After Launch

Every app crashes somewhere once real people use it on devices and networks you never tested. What matters is whether you find out, can read what happened, and fix the crashes that hurt the most people first. This guide covers the tools Apple and Google give you for free (the Crashes organizer in Xcode, MetricKit and Android vitals), what Google Play's bad behaviour thresholds mean, why crash reports need symbol and mapping files, what an SDK such as Firebase Crashlytics adds, and how crash data fits your privacy answers. It draws on Apple's developer documentation, Android developer documentation, Play Console help and Firebase documentation, checked on 3 November 2026.

What a crash report tells you

Apple's guide to diagnosing issues using crash reports and device logs explains that a crash report "describes how your app terminated, and also contains the complete backtrace of each thread, which shows the code running at the time of the crash." Android's page on crashes describes the same idea: a crash produces a stack trace, "a snapshot of the sequence of nested functions called in your program up to the moment it crashed." The type of error and the line of code where it was thrown are usually the strongest clues.

Crashes are not the only stability problem. On Android, an ANR ("Application Not Responding") is triggered when the app's main thread is blocked for too long, for example when the app has not responded to a key press or screen touch within 5 seconds. On Apple platforms the system can also end an app that uses too much memory, which produces a jetsam event report rather than a normal crash report. Android's documentation also points out that an app does not have to be on screen to crash: a component running in the background can crash it, which confuses users who were not using the app at the time.

Apple: the Crashes organizer and MetricKit

For apps distributed through TestFlight and the App Store, Apple collects crash reports for you. Its page on acquiring crash reports and diagnostic logs says the Crashes organizer in Xcode shows reports "from customers who share diagnostic and usage information", and that "TestFlight users of your app automatically share crash reports with you, regardless of the device settings for sharing diagnostic and use data." So the organizer shows crashes from App Store users who share diagnostics, not from every user.

Some report types do not appear in the Crashes organizer and have to be collected another way. Apple lists watchdog events (such as slow app launches), invalid code-signature crashes, thermal events and jetsam (high memory) events. If a customer reports a crash that you cannot find, Apple describes how they can find the log on their device under Analytics & Improvements in Settings and email it to you.

MetricKit is Apple's framework for collecting this data inside your own app. According to Apple, "The system delivers metric reports about the previous 24 hours to your app at most once per day," while diagnostic reports "arrive immediately in iOS 15 and later, and macOS 12 and later." It is useful when you want crash, hang and performance data in your own backend or dashboard rather than only in Xcode.

Android vitals and Google Play's thresholds

On Android, Google Play collects stability data through Android vitals. When a user allows it, their device tracks quality metrics such as stability, performance and battery use, and you see the results in Play Console. Play Console help on monitoring technical quality with Android vitals says the data comes from users "who have opted in to automatically share usage and diagnostics data."

Two stability measures are core vitals. The user-perceived crash rate is "The percentage of your daily users who experienced at least one user-perceived crash," and Google defines a user-perceived crash as "a crash that is likely to have been noticed by the user." The user-perceived ANR rate works the same way for ANRs. Google publishes bad behaviour thresholds for both:

  • User-perceived crash rate: 1.09% of daily users overall, or 8% on a single phone model.
  • User-perceived ANR rate: 0.47% of daily users overall, or 8% on a single phone model.

These numbers are not just a report card. The Android vitals page says core vitals "affect the visibility of your app on Google Play", and that if an app exceeds a threshold, Play may reduce its visibility and may show users a warning on the store listing. Play Console help adds that "Google Play will generally consider the last 28 days of data when evaluating your app's quality but may act sooner in the event of a spike." You can turn on email notifications for bad behaviours and for anomalies such as a sharp rise in the ANR rate.

Google's advice on what to fix first is practical: "fix the crashes and ANRs affecting the most users." If a problem shows up on one device model only, fix the biggest crash and ANR groups on that model.

Readable reports: symbols and mapping files

A release build does not carry the names of your functions, so a raw crash report shows memory addresses instead of code. Turning those back into function names and line numbers is called symbolication. Apple's page on adding identifiable symbol names to a crash report is blunt: "an unsymbolicated crash report is rarely useful." If you include debug symbols when you upload the app to App Store Connect, the Crashes organizer symbolicates reports for you. Apple also says to keep the Xcode archive for each build you distribute.

Android apps are usually shrunk and obfuscated for release, which renames classes and methods. The Android documentation on troubleshooting app optimization explains that a mapping file lets you recover the original stack trace, and warns: "The mapping file is overwritten every time you build your project, so you must save a copy each time you publish a new release." Play Console lets you upload the mapping file and native debug symbols for each version, but its help page on deobfuscating crash stack traces notes that "only crashes and ANRs that occur afterward will be deobfuscated." Upload them with the release, not after the first bad week.

Third-party crash tools need the same files. Firebase's documentation on getting readable reports says Crashlytics processes your dSYM (debug symbol) files automatically, usually through a script that uploads them during the build. When reports stay unreadable, the usual cause it names is that Xcode is not producing the dSYM files at all.

Crash reporting SDKs such as Crashlytics

The store tools only see users who share diagnostics and give you little context about what the user was doing. A crash reporting SDK inside the app fills that gap. Firebase Crashlytics, a widely used example, groups related crashes into issues so you can see whether one crash affects many users, and sends alerts for new, regressed and growing issues. Other services work in a similar way.

Firebase's guide to customizing crash reports lists the extra context you can add:

  • Custom keys: key-value pairs that record the app's state, such as the current screen or a feature setting, which you can then search and filter by.
  • Custom log messages: short notes about what happened before the crash.
  • User identifiers: Firebase suggests "an ID number, token, or hashed value", which lets support match a crash to a user's complaint.
  • Non-fatal exceptions: errors your code catches and reports without crashing. Firebase notes that Crashlytics stores only the most recent eight exceptions in a given app session.

Each of these is useful only if it answers a question you will actually ask when fixing a crash. Decide on a short list of keys and logs during the build, not one at a time after problems appear.

Crash data and privacy

Crash reports are data you collect from users, so they belong in your store privacy answers. Apple's App privacy details list Crash Data ("Such as crash logs") and Performance Data ("Such as launch time, hang rate, or energy use") under Diagnostics. Google Play's Data safety form has a Crash logs type: "Crash log data from your app. For example, the number of times your app has crashed, stack traces, or other information directly related to a crash." Our guide to App Store privacy labels and Google Play Data safety covers how to answer these forms.

Check what your crash SDK sends and keeps. Firebase's privacy and security page lists what Crashlytics collects, including installation identifiers, the device model, operating system version and stack traces, and says it keeps crash stack traces and associated identifiers for 90 days before starting to remove them. By default Crashlytics collects reports from all users. You can switch to opt-in reporting and send data only when your code allows it, but Firebase warns this "will reduce the accuracy of your app's event count and crash-free metrics."

The easiest privacy risk to avoid is the one you add yourself. Custom keys, logs and user IDs end up in the crash tool, so keep names, email addresses, health details and anything a user typed out of them, and use an internal or hashed ID instead of an email address. Our guide to measuring a mobile app covers consent and analytics events alongside crash reporting.

A routine after each release

Stability work is mostly habit. In the first days after a release, check the Crashes organizer, Android vitals and your crash tool for new or growing issues. Compare the crash and ANR rates with the previous version. Fix the issues affecting the most users first, then ones confined to one device model or operating system version. Add a test for each fix where you can, as Apple's guide suggests, so the same crash does not return. Our guide to mobile app maintenance covers the wider update cycle, and testing a mobile app covers catching crashes before release.

A checklist

  • Debug symbols are included when each iOS build is uploaded, and the Xcode archive is kept.
  • The Android mapping file and native debug symbols are saved and uploaded to Play Console for every release.
  • If you use a crash SDK, its symbol upload is part of the build and works for release builds.
  • Play Console email notifications are on for bad behaviours and anomalies.
  • Someone owns the crash dashboards and checks them after each release.
  • Custom keys, logs and user IDs contain no personal details beyond an internal or hashed ID.
  • Crash and diagnostic data are declared in the App Store and Google Play privacy answers.

Frequently asked questions

What crash rate is acceptable on Google Play?

Google publishes bad behaviour thresholds rather than a target: a user-perceived crash rate of 1.09% of daily users overall, or 8% on a single phone model, and a user-perceived ANR rate of 0.47% overall, or 8% on one model. Above them, Play may reduce the app's visibility and show a warning on the store listing.

Do we need Crashlytics if we already have Xcode and Android vitals?

Not always. The store tools are free but only include users who share diagnostics and give little context. A crash SDK adds custom keys, logs and alerts, but it is another service collecting user data that you must declare.

Why does our crash report show addresses or scrambled names instead of code?

The symbol or mapping files for that build are missing. Upload debug symbols with each iOS build and the mapping file to Play Console with each Android release. Play only deobfuscates crashes that happen after the file is uploaded.

What is an ANR?

Application Not Responding. Android triggers it when the app's main thread is blocked for too long, for example when it has not responded to a touch or key press within 5 seconds. Like crashes, ANRs count towards Android vitals.

Do crash reports need to be declared in the privacy labels?

If you collect them, yes. Apple lists Crash Data under Diagnostics in its App privacy details, and Google Play's Data safety form has a Crash logs data type. Include data collected by crash SDKs, not only your own code.

Planning an app or improving one you already have? We build iPhone and Android apps together with the backend, API and admin dashboard behind them. See our mobile app development service and all our services, or email [email protected].