Production visibility for an inherited mobile app
You have inherited a mobile app. Maybe the original development agency moved on. Maybe the in-house developer who built it left the company. Maybe you acquired the product through a business deal. Whatever the path, you now own a codebase you did not write, running in production, serving real users, and you have no visibility into what is going wrong.
Before refactoring, establish what the current release is doing. Crash reporting is one part of that picture, alongside ANRs or hangs, handled errors, backend failures, rollout state, and critical user journeys. Add telemetry deliberately because it may collect user or device data.
Why Inherited Apps Are Uniquely Fragile
Apps built by a previous team often lack the operational infrastructure that a long-term maintainer would put in place. Error handling may be inconsistent. Logging may be minimal or entirely absent. There is rarely a runbook documenting known issues or fragile areas of the codebase.
Without crash monitoring, you have two sources of information about app stability: user reviews in the app stores and support tickets. Both are lagging indicators. By the time a user writes a one-star review mentioning crashes, dozens or hundreds of other users have already experienced the same issue and silently moved on. Crash monitoring gives you the leading indicator you need to catch and fix issues before they reach that threshold.
Choosing a Crash Reporting Tool
The two most widely adopted tools for mobile crash reporting are Firebase Crashlytics and Sentry. Both are mature, well-documented, and supported across iOS and Android. Here is how they compare for the specific use case of an inherited app.
Firebase Crashlytics
Crashlytics is free, tightly integrated with the Firebase ecosystem, and extremely straightforward to set up. If the inherited app already uses Firebase for analytics, authentication, or push notifications, adding Crashlytics is often just a matter of enabling it in the Firebase console and adding a few lines of initialization code. The dashboard is simple and focused: it shows crash-free user percentage, top crash groups, and trends over time.
The limitation of Crashlytics is that it is primarily a crash reporter. It does not handle non-fatal errors, performance monitoring, or breadcrumb logging with the same depth as dedicated observability platforms.
Sentry
Sentry is a fuller error monitoring platform. It captures crashes, non-fatal exceptions, breadcrumbs (a trail of events leading up to the crash), and performance data. It supports source map and dSYM uploads for symbolicated stack traces, and it provides more powerful filtering and search capabilities than Crashlytics.
Sentry has a free tier that is generous enough for most small to mid-size apps. The paid tiers add features like session replay, profiling, and higher event volume. For an inherited app where you need to understand not just that something crashed but why, Sentry's breadcrumb and context features are particularly valuable.
For most teams inheriting an app, our recommendation is to start with Crashlytics if Firebase is already present in the project, and Sentry if it is not or if you need deeper diagnostic capabilities.
Integration: What to Expect
Integrating a crash reporting SDK into an existing app is generally low-risk, but there are a few things to be aware of when working with a codebase you did not write.
- Check for existing crash reporting. Before adding a new tool, search the codebase for existing integrations. Look for imports of Crashlytics, Sentry, Bugsnag, Instabug, or similar SDKs. Running two crash reporters simultaneously can cause conflicts, duplicate reports, and in rare cases, interfere with each other's signal handlers on iOS.
- Verify the build pipeline. Both Crashlytics and Sentry require a build phase step to upload debug symbols (dSYMs for iOS, mapping files for Android). If you cannot build and deploy the app from your own machine or CI pipeline, you need to solve that problem first. Crash reports without symbolication are nearly useless: you will see memory addresses instead of function names and line numbers.
- Add the SDK early in the app lifecycle. Initialize the crash reporting SDK as early as possible in the application startup sequence, ideally in
application:didFinishLaunchingWithOptions:on iOS or in theApplicationclass on Android. Crashes that occur before the SDK is initialized will not be captured. - Ship a build and wait. Once integrated, ship the updated build to production and wait at least one week before drawing conclusions. You need enough session volume to establish meaningful data.
Establishing a Crash-Free Rate Baseline
Crash-free users and crash-free sessions answer different questions. A long-session application may look healthy by sessions while repeatedly failing the same people. Track both when available, and segment by app version, OS version, device, and release cohort.
Choose a target from the current baseline and product consequence. A crash during an optional export is not equivalent to a crash that loses a field report or interrupts a medical recording. The number needs a time window, sample size, and owner.
When monitoring first goes live, preserve the baseline by app version, OS, device, release cohort, and affected workflow. Do not compare the app with a universal crash-free target. Compare each fix with the same population and enough time or sessions to show that the change is real.
Review the trend on a cadence appropriate to release volume, and inspect each rollout early enough to stop expansion. Prioritize by affected users, recurrence, consequence, and confidence in the fix rather than assuming a fixed number of crash groups will reach a universal target.
Triaging the Top Crashes
Both Crashlytics and Sentry group individual crash reports into crash groups based on the stack trace. The groups are ranked by the number of affected users. Start at the top.
For each of the top crash groups, answer these questions:
- What is the stack trace telling you? Read the symbolicated stack trace. Identify whether the crash is in your code, in a third-party library, or in the OS framework. Crashes in your own code are the easiest to fix. Crashes in third-party libraries may require updating the library. Crashes in OS frameworks may indicate misuse of an API.
- What is the frequency and trend? Is this crash increasing, stable, or decreasing? A crash that is increasing may be tied to a specific OS version or device model that is gaining market share.
- What is the user impact? A crash that occurs on the login screen affects every user. A crash that occurs in a rarely used settings page affects very few. Prioritize accordingly.
- Can you reproduce it? Use the device model, OS version, and breadcrumb data from the crash report to attempt reproduction. If you can reproduce it, you can fix it with confidence. If you cannot, you may need to add more logging around the affected code path and wait for additional data.
Setting Up Alerting
Crash monitoring is only useful if someone is actually looking at it. Configure alerts so that you are notified when stability degrades.
- New crash group alerts: Both Crashlytics and Sentry can notify you when a new, previously unseen crash type appears. This is especially important after shipping an update.
- Regression alerts: Sentry can detect when a previously resolved crash reappears. This is common when a dependency update reintroduces a bug or when a merge conflict silently reverts a fix.
- Threshold alerts: Set an alert if the crash-free rate drops below your target. A sudden drop often indicates a bad release or a backend change that the app is not handling gracefully.
Route these alerts to a Slack channel, email distribution list, or PagerDuty integration depending on your team's workflow. The goal is to reduce the time between a crash appearing in production and someone investigating it.
What Comes After Monitoring
Setting up crash monitoring is the foundation, not the finish line. Once you have visibility, the real maintenance work begins: fixing the top crashes, updating stale dependencies, removing dead code, and gradually improving the stability and maintainability of the codebase you inherited.
But none of that work is possible without data. The crash monitoring setup gives you the map. Everything else follows from there.
DEVSFLOW Maintenance establishes production telemetry and incident processes for inherited mobile applications. Review the standard maintenance scope.