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:
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.
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.
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.
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.
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.
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
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.
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.
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.
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
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.
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
Watch the short video below to learn how to install the Kotzilla SDK in your Kotlin project and start detecting and preventing ANRs today.