Modern Android apps are composed of dozens (or hundreds) of modules, each containing components...
How to Prevent and Fix ANRs in Kotlin and KMP Apps: A Pratical Guide
Kotlin or Multiplatform app freezing up and causing ANRs?
Learn to detect, debug, and fix ANRs from long component resolution blocking the main thread with the Kotzilla Platform, the Application Performance Monitoring (APM) tool for Kotlin developers using Koin and working on Android or Kotlin Multiplatform (KMP) projects.
Before we dive into the technical details, here's what you'll learn and be able to implement by the end of this guide:
Kotlin ANRs are preventable with the right detection and monitoring approach
- Detection: If you're building with Koin, use the Kotzilla Platform for automatic ANR risk monitoring
- Prevention: Keep Kotlin component initialization under 100ms on the main thread
- Solutions: Move heavy operations to background threads with proper Kotlin coroutines dispatchers
- Monitoring: Set up continuous ANR monitoring for production Kotlin apps
By following these ANR prevention best practices and using proper monitoring tools, you can eliminate ANRs and create smooth, responsive Kotlin apps that users love 💛
Now let's start with the fundamentals: understanding what actually causes these frustrating performance issues in the first place.
What Causes ANRs in your Kotlin App?
Kotlin ANRs (Application Not Responding) happen when your main thread gets blocked for too long, basically when you're doing heavy work on the UI thread that should be happening in the background.
On Android, these issues may trigger the system’s ANR dialog. On iOS (or other KMP targets), the same blocking behavior leads to UI freezes or watchdog-triggered app termination.
The primary causes are:
- Heavy operations during component initialization (like in constructors/init blocks)
- Synchronous database queries or network calls
- File I/O, JSON parsing, or image processing on the main thread
- Complex calculations that take more than 100ms
What happens in the real world: Users notice slowness well before Android’s 5-second ANR dialog appears. By that time, it is already too late because slow apps get bad reviews, more uninstalls, and lower app store rankings.
The fix: Move heavy work to background threads using Kotlin coroutines and proper threading patterns. Keep component initialization lightweight and defer expensive operations.
How the Kotzilla Platform detects and prevents ANRs in Kotlin and KMP apps
Automatic ANR detection for Kotlin components using Koin
The Kotzilla Platform continuously monitors component initialization in your Kotlin app and flags any main thread operations that take longer than 100ms. This allows you to catch and fix performance problems that can lead to ANRs before they impact users.
Main Thread Performance issue = ANR or potential ANR
Not every flagged issue is an ANR yet, but many are on their way to becoming one. The platform focuses on identifying main thread performance issues that, if left unresolved, will likely cause an Application Not Responding (ANR) dialog, especially if they exceed 400ms during key moments of user session.
The Kotzilla Platform shows you the severity of issues
When the Platform detects a main thread performance issue in your Kotlin app, it doesn't just flag it as "slow", it assigns a specific severity level to help you prioritize which problems need immediate attention versus those that can be addressed later.
How does it do this? It calculates a severity score for main thread blocking issues based on how much the measured blocking time exceeds predefined performance thresholds. The platform uses 100ms as the baseline target (where any blocking above this gets flagged) and 400ms as the tolerance threshold (where issues become critical).
In the example below, you will see a ViewModel resolution in the "Now In Android" app that blocks the main thread and is flagged as critical in the Kotzilla Dashboard view, meaning the resolution takes over 400ms.
Investigating the Root Causes of ANRs
When the Kotzilla platform has detected a main thread performance issue, your focus should now be on investigating what’s happening during component initialization, especially which operations are running too long on the UI thread.
For that, you can click on the issue to get more details and continue the analysis by checking how many user sessions are impacted and what the resolution time was for this ViewModel in each session. We immediately see here a user session where the resolution time took 1.01 seconds. You can filter user sessions by app version, device, operating system and others.
Clicking on this user session will take you to a Timeline view, already positioned at the exact moment the issue occurs, showing the full context of the long component resolution, including thread execution and an overview of the dependencies resolution.
The Kotzilla Platform even shows the complete details of the dependency graph for this specific ViewModel, helping you identify whether there is also slow dependency resolution or if the cause of the problem is the component's own initialization. You'll also notice that the tool provides clear recommendations about the source of the issue. In this example, it appears to be related to the MainActivityViewModel
initialization code
Recommended actions to fix an ANR in Kotlin apps
✅ Offload heavy work to background threads
Avoid executing time-consuming operations like I/O, networking, or parsing directly on the UI thread. Use coroutines with proper dispatchers (i.e. Dispatchers.Default
) to move these tasks off the main thread and maintain smooth user interactions.
✅ Apply Koin lazy dependency loading
Although Koin singletons are lazy by default, premature calls like get()
or use of createdAtStart()
can trigger early initialization. Use the inject()
delegate to delay dependency resolution until it’s actually needed. This is especially helpful for non-essential services such as analytics or remote config.
✅ Refactor and isolate heavy components
If your dependency graph is too large or tightly coupled, it may still cause blocking during resolution. Refactor these into smaller, more focused modules. Isolate optional or resource-heavy components and load them asynchronously if possible, reducing the impact on the main thread during critical moments.
If further context is needed, the Kotzilla SDK API can be used alongside the Timeline view of the platform to add custom logs, trace execution times, and instrument specific parts of your component init code.
Debug in development, monitor in Production
The Kotzilla Platform isn’t just for debugging during development. The Kotzilla SDK is lightweight and production-safe, meaning you can integrate it into live apps without worrying about introducing performance overhead or impacting your users’ experience.
Once deployed, the SDK continuously captures performance data from real user sessions, giving you deep visibility into:
-
Which components are blocking the main thread in real-world conditions
-
Which app versions or devices are most affected
-
How often users encounter delays or ANR risks
-
Resolution times across different contexts and environments
With this production insight, you can catch issues that don’t surface in testing and prioritize what to fix based on real user impact
Fix ANR's directly from Android Studio with the Koin IDE Plugin
The Kotzilla Platform is tightly integrated with your existing Kotlin development workflow through the Koin IDE Plugin, allowing you to go from detection → analysis → fix without leaving Android Studio or IntelliJ.
Here’s how it works:
-
Open the Koin Insights View of the Koin IDE Plugin inside Android Studio
-
Navigate to the Application Issues tab to view flagged main thread performance issues
-
Access Kotzilla Console directly from the IDE, including full Timeline views
-
Apply recommended fixes right in your code, using contextual information
You can use the plugin to quickly navigate your code and identify what was blocking in the MainActivityViewModel
component, speeding up root cause resolution and minimizing context switching. Whether you're analyzing performance problems or implementing fixes, this tight loop helps you move faster and stay focused.
In the example below, you can see that the cause of this main thread performance issue was an artificial 1-second delay introduced during the initialization of the ViewModel.
Build reliable Kotlin and KMP apps with the Kotzilla Platform
ANR prevention isn’t just a technical win, it’s a user experience and business win. Unresponsive apps frustrate users, lead to bad reviews, and damage your app’s reputation in both Play Store and Apple Store. Whether you're building for Android or using Kotlin Multiplatform, catching and fixing main thread performance issues early is essential.
The Kotzilla Playform helps you do just that:
-
Real-time detection of ANR risks before they reach users
-
Insightful analysis with severity scoring and dependency graph visibility
-
IDE integration with Android Studio for smoother debugging
-
Production monitoring across Android and iOS with real user session data
-
Built for Kotlin, with full Koin support and coroutine-friendly recommendations
Want to give it a try?
Watch the short video below to learn how to install the Kotzilla SDK in your Kotlin project and start detecting and preventing ANRs today.