What Is a Good App Crash Rate? Crashlytics and Google Play Thresholds

Short answer
What is an app crash rate and why does it matter?
An app crash rate is the share of your users who hit at least one crash in a given period. Google Play measures it per daily active user and may reduce the store visibility of apps that cross its published thresholds. In short, your crash rate affects both user experience and how many people find your app.
Picture a shopper who opens your app, fills the cart and watches it close on the payment screen. As a result, that person rarely tries again. They may also leave a one-star review on the way out. So we suggest treating crashes as lost revenue and lost trust, not only as a bug ticket.
At Talha Aslan and team, we treat the first weeks after a release as the most sensitive period of any mobile project. This guide walks you through the Google Play thresholds, how Apple handles crashes, tracking with Crashlytics, how to decide what to fix first, and a post-release monitoring checklist.
What is the difference between a crash, an ANR and a hang?
A crash happens when the app closes suddenly because of an unexpected error. Specifically, the user sees the app vanish and lands back on the home screen. For example, a line of code that tries to read a missing value from a server response can take the whole app down.
ANR stands for "Application Not Responding" and it is specific to Android. According to the Android developer documentation, an ANR triggers when the UI thread of an app stays blocked for too long. In practice, the user sees a frozen screen that ignores taps.
A hang is a broader term, and you will see it on iOS too. It describes an interface that stops responding for a while. From the user's point of view, the difference is small, because in all three cases they cannot finish what they came to do.
- Crash: The app closes and the user has to start over.
- ANR: The app stays open but freezes, and the system offers to wait or close it.
- Non-fatal error: The app keeps running, but an action fails silently.
Crash rate and ANR rate carry the most weight in store quality checks. Non-fatal errors do not count toward store thresholds. Still, they damage the experience, so you should track them as well.
What is the Google Play app crash rate threshold?
Google publishes two separate limits, called bad behavior thresholds: an overall threshold and a per-device threshold. The values below come from the Android vitals page on Android Developers at the time we wrote this guide. However, Google can change them, so always check the current values on the official page.
| Metric | Overall threshold (all devices) | Single phone model threshold |
|---|---|---|
| User-perceived crash rate | 1.09% | 8% |
| User-perceived ANR rate | 0.47% | 8% |
The overall threshold looks at the share of daily active users across all device models who experienced a crash. The per-device threshold looks at one phone model on its own. In other words, your app can look healthy on average and still cross the threshold on a specific model.
Google lists separate, stricter values for watch apps. Also note that the thresholds cover user-perceived crashes only. Background crashes that the user never notices do not count, except on Wear OS.
What happens when your app crosses a Google Play threshold?
According to the Android vitals page, if your app exceeds a bad behavior threshold, Play may reduce the visibility of your title. Play may also show users a warning on your store listing. Together, these two outcomes hurt both discovery and the install decision.
Specifically, the impact depends on which threshold you cross. Google's crash page says an app above the overall threshold is likely to be less discoverable on all devices. An app above the per-device threshold is likely to be less discoverable on those devices, and its listing may show a warning.
- Evaluation window: Play uses the last 28 days of data and checks your key indicators daily against that 28-day average.
- Emerging issues: Android vitals flags crash and ANR problems that have affected devices for over 7 days, and gives you 21 days to address them.
- Recovery: Android vitals warnings disappear once the average improves, and store listing warnings may go away faster if Play detects the improvement.
The takeaway, therefore, is simple. You will not see results on the day you ship a fix. Instead, the average recovers as the new version spreads across the 28-day window. That is why catching problems early costs far less than fixing them later.
How does the App Store handle crashing apps?
Apple does not publish a public percentage threshold like Google Play does. Instead, it deals with crashes during review. Guideline 2.1 of the App Store Review Guidelines asks you to test your app on-device for bugs and stability before you submit it. The same guideline states that Apple will reject binaries that crash or exhibit obvious technical problems.
So on iOS, most of the risk sits before launch. If the reviewer opens your app and it crashes on the login screen, the build gets rejected and your release date slips. We collected the most common causes in our guide on why apps get rejected.
The design section of the guidelines also says that apps that stop working or offer a degraded experience may be removed at any time. Therefore crash monitoring after launch is not optional on iOS either.
On the Apple side, you follow crash data in the Organizer window inside Xcode. According to Apple's documentation on crash reports, it shows reports from customers who opt in to sharing diagnostic data. TestFlight testers, on the other hand, share crash reports with you regardless of that device setting.
How does Google calculate the user-perceived crash rate?
Google's crash page defines the user-perceived crash rate as the percentage of daily active users who experienced at least one crash while actively using your app. An app counts as in active use if it is displaying any activity or running a foreground service.
Next, the definition of a daily active user matters here. If one person opens your app on two devices on the same day, each device counts as a separate user. On the other hand, several people sharing one device on the same day count as one active user.
Android vitals also measures per daily active user, not per session. Google gives a clear example. If a user opens three sessions in a day and one of them crashes, Android vitals shows 100%, while a per-session tool might show 33%.
Example calculation: Imagine an app with 20,000 active devices on a given day. If 160 of those users hit at least one crash, the daily rate is 160 / 20,000 = 0.8%. That sits below the overall threshold. Now suppose 120 of those crashes happened on a single phone model with 1,000 active users. That model's rate is 12%, so your app crosses the per-device threshold.
This example shows why the overall average alone is not enough. For that reason, we recommend opening the device breakdown in Play Console every week.
What is Crashlytics and what does it do?
Firebase Crashlytics is the real-time crash reporting tool in Google's Firebase platform. According to the Firebase documentation, it supports iOS, Android, Android NDK, Flutter and Unity. When your app crashes, it sends the stack trace and device details to the dashboard. A stack trace is the list of code lines that led to the error.
Above all, grouping is its biggest strength. Crashlytics bundles thousands of crashes from the same root cause into a single issue by analyzing stack frames, exception messages and error codes. As a result, you work through a few dozen issues instead of thousands of raw reports.
- Real-time alerts: You get notified about new, regressed and growing issues.
- Variants: You can tell apart different root causes inside the same issue.
- Non-fatal errors: You can also log errors that break an action without closing the app.
- Custom keys and logs: You attach the state of the app just before the crash.
Android vitals and Crashlytics do not compete. Android vitals tells you how the store sees you, while Crashlytics gives you the detail you need to find and fix the bug. Moreover, Crashlytics offers the same dashboard on iOS, so you can watch both platforms in one place.
What are the steps to set up Crashlytics?
The technical details depend on your stack. Native Android, native iOS, Flutter and React Native projects each follow slightly different steps. That said, the general flow looks similar everywhere:
- Create a project in the Firebase console and register your Android and iOS apps in it.
- Add the platform configuration file to your project and include the Crashlytics package in your dependencies.
- Set up automatic upload of symbol files during the build: the mapping file on Android and the dSYM on iOS.
- Force a test crash in a debug build and confirm the report reaches the dashboard.
- Update your privacy policy and data collection settings, and enable opt-in reporting if you need it.
- Route alerts to a channel your team actually reads.
Do not skip step four. Many teams think the setup is done, then meet an unreadable stack trace at the first real crash because the symbol files never uploaded. For the broader testing mindset, see our pre-launch QA checklist; the same logic applies to mobile releases.
What do crash-free users and crash-free sessions tell you?
You will see two core rates in the Crashlytics dashboard. According to Firebase's page on crash-free metrics, crash-free users is the percentage of users who engaged with your app during the selected period without a crash. Crash-free sessions is the percentage of sessions that did not end in a crash.
Firebase calculates both as an aggregation over time, not an average. That is why it advises against comparing different time periods, since longer periods usually produce lower values. For example, comparing a 7-day figure with a 30-day figure can lead you to the wrong conclusion.
Two more details deserve attention. First, these rates only cover fatal events, so filtering the dashboard to non-fatals or ANRs leaves the charts blank. Second, if you turn on opt-in reporting, data comes only from users who agreed, and the numbers may not represent your whole audience.
So is the app crash rate the same as the crash-free users rate? Not exactly. Android vitals uses its own definition of daily active users and active use, while Crashlytics relies on its own user and session logic. Because of this, the two dashboards rarely match one to one.
How do Android vitals, Crashlytics and Xcode Organizer compare?
Put simply, each tool answers a different question. Knowing which tool does what ends the "which number are we looking at" debate inside the team. The table below summarizes the comparison based on the official documentation:
| Feature | Android vitals (Play Console) | Firebase Crashlytics | Xcode Organizer |
|---|---|---|---|
| Platform | Android only | iOS, Android, Flutter, Unity | Apple platforms only |
| Core measure | Crashes and ANRs per daily active user | Crash-free users and sessions | Crash reports from users who share diagnostics |
| Store impact | Direct, thresholds affect visibility | None, it is a diagnostic tool | No public threshold |
| Setup | Publishing on Play is enough | Requires adding the SDK | Ready for App Store and TestFlight builds |
| Context data | Device, Android version, stack trace | Custom keys, logs, breadcrumbs | Stack trace and device details |
In practice, we recommend using all three together. Android vitals warns you about store risk, Crashlytics shows you the cause, and Organizer gives you Apple's own data on iOS.
Which crash should you fix first?
You cannot fix every crash at once, so you need a clear order. Google's Android vitals advice is direct: fix the crashes and ANRs affecting the most users first. To improve quality on specific devices, fix the biggest groups on those devices. If you face both, focus first on the largest overall clusters.
We add business impact on top of that advice. When two bugs hit the same number of users, the one on the payment screen always beats the one in settings.
- Affected users: Look at how many distinct users hit the issue, not the total crash count.
- Distance to the threshold: An issue pushing one phone model toward the per-device limit threatens store visibility.
- Critical flows: Put crashes in login, sign-up, cart and checkout at the top.
- New or regressed: An issue that appeared with the latest version usually ties to the latest change, so it tends to be quick to fix.
- Growth speed: An issue that grows every day can be more urgent than a large one that stays flat.
Repeat this ranking after every release. That way, your team spends time on the bug that does the most damage, not the one that makes the most noise.
How do you turn an unreadable stack trace into a readable one?
Build tools usually shrink and obfuscate code in release builds. On Android, this turns class and method names into short letters. On iOS, crash reports contain raw memory addresses. Without mapping data, your stack trace becomes a list of meaningless lines like "a.b.c".
The fix is to keep the symbol file for every build and upload it to the right tool. On Android, you provide the mapping file to both Play Console and Crashlytics. On iOS, the dSYM file translates addresses into function names and line numbers.
- Tie symbol upload to your build pipeline instead of relying on manual uploads.
- Archive the symbol file for each version number, because crashes from an old version can arrive months later.
- In cross-platform frameworks such as Flutter or React Native, check the symbols of the native layer and the framework separately.
An unreadable stack trace makes your team burn hours on guesswork. Therefore make symbol upload a mandatory item on your setup checklist.
Why do custom keys, logs and breadcrumbs matter?
A stack trace tells you where the error happened, but not always why. According to Firebase's guide on customizing crash reports, you can add custom keys, custom log messages and a user identifier to Crashlytics. Breadcrumb logs also show the user interactions that led up to a crash.
For example, keys like "selected language", "items in cart" or "active payment method" quickly reveal that a bug only appears under one condition. As a result, reproducing the issue takes minutes instead of days.
Mind the privacy line, though. Do not write names, phone numbers, email addresses or card data into crash reports. If you need a user identifier, use an anonymous ID from your own system. Also keep your data collection settings in line with your privacy policy and the store privacy forms. This is not legal advice; review your data handling with your legal counsel.
Finally, keep server-side errors in mind. In many cases the real cause of a crash is a server response in an unexpected shape. We explain that connection in our article on what an API is.
What are the most common causes of crashes?
Every project has its own error profile. Still, the patterns we see most in the field look alike. The list below is not a statistic. Instead, treat it as a starting checklist based on field experience:
- Null or unexpected data: The server returns a missing field and the code never expected it.
- Memory pressure: Loading large images without resizing them kills the app on low-memory devices.
- Lifecycle bugs: A late response tries to update a screen that the user already closed.
- Permission and OS changes: A new operating system version changes permission behavior and breaks older code.
- Third-party libraries: An outdated SDK stops working with a new system version.
- Device fragmentation: One manufacturer's software layer causes crashes only on its models.
The last item explains why the per-device threshold matters. On Android especially, with hundreds of models in use, pick your test devices based on the real distribution of your users.
How can you lower your ANR rate?
According to Google's ANR page, only ANRs of the type "Input dispatching timed out" currently count as user-perceived. In practice, this metric rises when your app fails to respond to a user's touch in time. These ANRs always happen while the user is engaged with the app, so they cause the most disruption.
What ANRs share is a main thread that stays busy for too long. So the first place to look is any work other than drawing the screen that runs on the main thread.
- Move network calls and file reads and writes to background threads.
- Cut the work your app does at launch and defer anything optional.
- Load long lists and images in chunks.
- Review shared resources that cause lock contention.
Caching also reduces ANR risk, because you stop recalculating the same data again and again. You can read about the server-side side of caching in our guide on how caching works.
How does a staged rollout reduce crash risk?
A staged rollout means you release a new version to a small share of users first. Google Play calls this a staged rollout, and App Store Connect calls its version a phased release. That way, a crash in the new version reaches a small group instead of your entire user base.
Above all, the value lies in the decision point it creates. While the new version runs for a small group, you watch Crashlytics for new issues and for changes in the crash-free users rate. If the numbers look worse than expected, you pause the rollout, prepare a fix and then continue.
Example scenario: An ecommerce app ships a new checkout screen through a staged rollout. On day one, Crashlytics shows a new issue on the checkout screen for one Android version. The team pauses the rollout and moves the fix into the next build. As a result, the issue closes before it reaches most users, and the 28-day average stays largely intact.
Also use internal testing tracks before any public rollout. We cover the role of test automation in that process in our article on what a test automation engineer does.
Is crash tracking different in cross-platform apps?
Apps built with Flutter or React Native have two layers: the framework code and the native Android and iOS layer underneath. Because of this, a crash can come from two different places. Crashlytics officially supports Flutter, but you still need to check error capture settings in each layer.
For example, an uncaught error in the Dart or JavaScript layer can leave a blank screen without closing the app. The user experiences that as a crash, yet store metrics may not count it as one. Therefore we recommend reporting framework-level errors as non-fatal events.
Also remember that native dependencies change when you upgrade the framework version. Ship the first release after such an upgrade through a staged rollout and watch the device breakdown closely.
Post-release monitoring checklist
The first days after a new version goes live are the most critical for your app crash rate. You can reuse the list below for every release:
- First hours: Check Crashlytics for issues and alerts tied to the new version.
- Day one: Compare the crash-free users rate with the previous version over a period of the same length.
- Days two and three: Open the device breakdown in Android vitals and look for a single model with a rising rate.
- End of week one: Review non-fatal errors and the ANR list.
- Weekly: Read store reviews and match complaints like "keeps closing" or "freezes" to your crash list.
- Monthly: Check third-party SDK versions and changes in target operating system requirements.
- Every release: Confirm that symbol files uploaded.
The list looks long, but once it becomes a habit it fits into a short weekly review. The key is to give one person clear ownership of it.
Also log the result of each check in a short note. Even a single line such as "version 3.2, day one, no new issues" makes it much easier to find when a regression started months later.
How does crash rate affect reviews and removal risk?
A crashing app usually shows up in reviews first, often before anyone on the team checks the app crash rate dashboard. Users write "won't open" or "closes at checkout", and the rating drops. A lower rating then pulls down store conversion, so crashes also cost you installs indirectly.
On the other hand, crashes are not always a direct reason for removal. On Google Play, removals mostly relate to policy violations, which we cover in our guide on Google Play app removals. Apple's guidelines, however, clearly state that apps that stop working may be removed from the store.
In short, do not treat crash rate as an engineering-only metric. If your app crashes while your marketing team spends ad budget, the users that ads bring in disappear in their first session.
What app crash rate should you aim for?
Put simply, there is no single answer that fits every app. The store threshold is a floor, not a target. An app sitting just below it avoids the store penalty, yet it still loses some of its users every day.
We suggest setting your goal by trend rather than by an absolute number. Each version's crash-free users rate should not fall below the previous one, and no phone model should approach the per-device threshold. This works better than leaning on industry averages with unclear sources.
Draw a baseline for your own app: record the values of your last three versions and compare each new release against that line. A clear drop below the line is a good enough signal to pause a rollout.
When should you get professional help with your app crash rate?
Outside help makes sense if you have no mobile developer in-house, if another company built and handed over the app, or if an Android vitals warning has stayed for weeks. Diagnosis also takes longer when symbol files are missing, source access is limited or the cross-platform layer is complex.
Through our mobile app development service, we build your app and take it to the stores for you. We set up Crashlytics, the symbol upload pipeline and the post-release monitoring routine as part of the job. We handle stability problems in existing apps within the same framework.
If you face a different problem such as a store rejection, our article on the Guideline 4.3 spam rejection may help. If you want us to handle your app's stability and release process together, you can request a quote on our mobile app development page. In the quote, we clarify your current state, target platforms and release timeline.



