As the Kotlin language has grown, the projects built with it have become increasingly complex. And...
Going Beyond Firebase: Performance Monitoring for Kotlin Apps using Koin with the Kotzilla Platform
As Kotlin developers, we all want our apps to feel fast and smooth: quick startup, responsive UI, no weird freezes.
Firebase Performance Monitoring provides a great starting point with built-in metrics like app startup time, screen rendering, and network calls. But when it comes to uncovering deeper performance issues and their root causes, such as why your app is becoming slow or unresponsive due to a ViewModel blocking the main thread, Firebase relies on you to add custom traces manually
That means searching through your code, deciding where to place those traces, and hoping they catch the real problem. This process can get tedious and often leaves gaps, especially in complex Kotlin apps with many critical execution paths.
I work at Kotzilla, where we saw these limitations firsthand. That is why we built the Kotzilla Platform, designed specifically for Kotlin apps, especially those using Koin. It automatically tracks components, dependency lifecycles, and thread activity without extra code, giving you clear, Koin-level visibility into the critical performance issues in your apps. The Kotzilla SDK leverages the Koin container to provide this unique insight.
I tested Firebase and the Kotzilla Platform side-by-side on Google’s NowInAndroid app, deliberately slowing things down to see what each tool would reveal. Firebase offered broad stats but missed the fine details I needed. The Kotzilla Platform gave me the deep insights I was after.
Let me walk you through what I found.
Testing both tools on a real app: NowInAndroid
To ground this comparison in reality, I tested both tools on Google’s official NowInAndroid app, which we migrated from Hilt to Koin for dependency injection.
NowInAndroid is a fully functional Android app built entirely with Kotlin and Jetpack Compose. It follows Android design and development best practices and serves as a helpful reference for developers. It’s meant to keep developers up-to-date with the Android world by providing regular news updates.
The setup
For this comparison, I followed the official getting started guides from Firebase Performance Monitoring and Kotzilla Platform to integrate the SDKs into the NowInAndroid app.
I created two separate Android Studio projects by cloning the NowInAndroid app for Koin, available here. Then, I introduced deliberate delays to simulate some performance issues in the following classes:
- Scenario 1: A 1-second blocking delay on the main thread in
MainActivityViewModel.kt
- Scenario 2: A 10-second delay during app startup in
NiaApplication.kt
- Scenario 3: A 1-second delay in a background task inside
SyncWorker.kt
These scenarios cover a range of common, yet hard-to-detect, performance issues: UI thread blocking, slow app startup, and background execution delays.
Here’s an example of the delay added to MainActivityViewModel.kt
:
Firebase Performance Monitoring: what it shows… and what it doesn’t
Firebase automatically monitors these traces:
- App Startup: Time from app launch until it becomes responsive (i.e,
onResume()
is called). - App Background: Time from when the last activity enters the background (
onStop()
) until any activity returns to the foreground (onResume()
). - App Foreground: Time while the app is actively in use, from
onResume()
toonStop()
. - HTTP/S Network Requests: Duration, size, and success rates of HTTP/S requests.
Firebase also provides a custom trace API so you can manually instrument specific parts of your app’s lifecycle.
But here’s what I found across these scenarios:
I ran the app multiple times, progressively introducing the three delays across user sessions, and connected it to the Firebase Console to evaluate what the platform could detect out of the box.
Note: Firebase delays in surfacing session data (often 10+ minutes, sometimes hours) made rapid debugging in debug builds difficult. Several samples with deliberate delays never appeared in the Firebase Console at all.
Scenarios 1 & 2: App start time & ViewModel resolution delays
-
The average app startup time increased as expected when introducing a 10-second delay in
NiaApplication.kt
and a 1-second delay inMainActivityViewModel.kt
. -
I configured Firebase to track default metrics: app startup time, time in background, time in foreground, and
MainActivity
duration. -
However, drilling into session details revealed no insights into what caused the delays, only percentile distributions across recorded sessions for each metric.
-
Firebase offered no automatic tracking of ViewModel resolution time, main thread blocking, or any indicator of the underlying issue (only visual graphs of startup evolution and app state durations).
-
To get additional detail, I had to manually add custom traces. Below is an example of a trace I created to monitor startup performance.
-
In this case, adding the trace was straightforward because I knew I was testing startup issues. But delays caused by ViewModel resolution would be much harder to detect without guessing where to add instrumentation in advance. Unless I already identified the app's critical paths and traced them during development, these would go unnoticed.
Note: During testing, it was also challenging to find real user sessions to analyze. Out of 12 runs, only 2 specific user sessions with performance data eventually surfaced after nearly two days.
-
This view revealed some impact on startup and screen appearance, along with basic CPU and memory usage but still no information about what was causing the problem or a way to isolate and analyze that user session.
Scenario 3: Background Worker Delay
-
The 1-second delay in
SyncWorker.kt
was completely invisible in Firebase’s default reporting. -
While Firebase monitors foreground and background durations, it provides no visibility into background worker or thread-level execution. As a result, you cannot tell whether time spent in the background was due to normal app suspension or a performance issue like a thread bottleneck or long-running task.
-
Spotting performance issues in background tasks requires even more manual instrumentation. Without it, worker-related delays remain undetected—even when examining specific user sessions:
General limitations of Firebase Performance Monitoring
Firebase provides general metrics, such as app start time and screen rendering, but do not provide detailed insights to identify performance issues related to ViewModels, asynchronous execution or multithreading.
-
Lack of granularity
Performance issues often arise from operations within ViewModels, including data loading and processing. Firebase does not automatically track these aspects, requiring custom traces to diagnose delays effectively.
Developers must anticipate and instrument critical app paths manually and maintain this tracing code over time.
This would require to initialize Firebase Performance Monitoring in the
NiaApplication
and then implement custom traces in all the classes and components that we would like to track, suchMainActivity
orMainActivityViewModel
-
Asynchronous execution and multithreading issues
Firebase Performance Monitoring does not adequately capture problems associated with asynchronous execution and multithreading. As such, it may not provide a complete picture of how background tasks and thread utilization impact app performance. Those issues can be addressed programmatically using the Firebase APIs but this kind of approach requires major code instrumentation.
Firebase is often used in combination with Android Studio’s CPU Profiler to help with the analysis of thread activity and identify issues related to asynchronous execution and multithreading.
Kotzilla Platform: deep Koin-level performance visibility for Kotlin apps
To simulate realistic delays, I introduced identical slowdowns in specific classes and ran the app multiple times using a debug build to generate user sessions across three scenarios.
The initial key difference was that the Kotzilla Console immediately identified multiple issues related to those scenarios. It provided an overview with categorization, impacted session count, and severity levels.
With these scenarios, Kotzilla delivered the following insights:
With these scenarios, the Kotzilla Platform delivered the following insights:
Scenario 1: 1-second delay blocking the main thread during MainActivityViewModel
resolution
Kotzilla automatically detected a 1-second main thread block caused by MainActivityViewModel
resolution. The console pinpointed the exact blocking call, categorized it as critical, and provided initial analysis, impact summary, and actionable recommendations.
I could filter and select a specific user session to investigate further using a dedicated timeline view showing key moments, such as screen transitions and detected issues, including performance bottlenecks and crashes.
The timeline was automatically focused on the exact moment the issue occurred. This provided complete context around the problematic component, including its resolution time (+1s) and thread activity; confirming the main thread was blocked.
Since Kotzilla integrates with the Koin container, I was also able to explore the full dependency graph of that component to investigate whether any dependency resolutions were slower than expected.
One of the dependencies took more than 15ms to resolve, but the bulk of the delay was due to the MainActivityViewModel
itself; making it easy to pinpoint the source of the 1-second delay as the initialisation of the ViewModel.
Scenario 2: 10-second delay in app startup
The Kotzilla Platform detected a 10-second delay during app startup, providing exact resolution times for every component in the dependency graph. It clearly showed how the main thread was blocked, delaying UI readiness.
In the timeline, you can see the main thread blockage and the 1-second delay before the first screen appeared. Users can also see the threshold used to trigger this slow startup issue.
Scenario 3: 1-second delay in SyncWorker
execution
Kotzilla identified a 1-second delay in the background thread during the SyncWorker
task. It provided deep visibility into the timing and impact of this delay on overall app performance.
Thanks to the Timeline view I was able to observe that:
- The SyncWorker was blocking a background thread for more than 1000ms.
- Several dependencies tied to the SyncWorker have performance issues due to delayed task resolution.
- The background thread performance is impacted by the complexity of the dependency graph, with 31 dependencies involved in the background task resolution.
And all of this came without manual tracing or custom instrumentation.
Still can’t get enough of tracing?
The Kotzilla Platform also offers a dedicated SDK API that lets you define custom traces, logs, and contextual properties. This is ideal for advanced debugging or adding specific data or properties where needed.
With the Kotzilla SDK API, you can:
- Log custom messages to your app’s performance timeline using
log("message")
- Record exceptions with
log("error message", exception)
- Benchmark specific code blocks using
trace("block_name") { ... }
- Add contextual data to sessions with
setProperties(...)
- Link sessions to specific users via
setUserId("user_123")
The API works on both Android and Kotlin Multiplatform (KMP) projects and is easy to set up:
- On Android: use
analytics()
inside yourstartKoin
block. - On KMP: initialize it with
KotzillaCoreSDK.setup(...)
incommonMain
.
This gives you fine-grained control over what gets tracked, when, and how, helping you debug and optimize even the most complex flows.
Firebase Performance Monitoring vs Kotzilla Platform: side-by-side comparison
Feature | Firebase Performance Monitoring | Kotzilla Platform |
---|---|---|
Components execution tracking and behaviour (ie ViewModels) | 🚫 Not automatic (manual traces required) | ✅ Built-in for Koin |
Dependency graphs visualisation and resolutions insights | 🚫 Not available | ✅ Built-in for Koin |
Thread execution visibility and performance | 🚫 Limited (manual traces required) | ✅ Built-in (main and background threads) |
Issues detection and root cause analysis | 🚫 Not directly supported | ✅ Dashboards for issues and root cause analysis tools |
Session-level performance data | ⚠️ May be delayed or partial | ✅ Graphical timeline, session-specific, real-time |
Instrumentation effort | ⚠️ Moderate to high for custom traces | ✅ Minimal (automatic + optional SDK) |
Crash reporting and session context | ⚠️ Separate Crashlytics setup; no unified view | ✅ Unified crash & performance data with full session context |
Cross-platform support | ✅ Broad (Android, iOS, web) | ⚠️ Kotlin-only (Android + KMP using Koin) |
Network monitoring (HTTP/S requests) | ✅ Built-in | 🚫 Not natively supported |
Conclusion
For Kotlin developers, getting deep, actionable performance insights shouldn’t require endless manual tracing. While Firebase Performance Monitoring provides useful high-level metrics, it often falls short when you need to understand the real performance issues and internals of modern Kotlin apps.
That’s why we built the Kotzilla Platform. It fills this gap with automatic, Koin-level visibility that pinpoints exactly where your app’s performance bottlenecks are. No more searching through code or relying on custom traces to catch the real issues. The Platform tracks component and dependency lifecycles, thread execution, and app behavior out of the box, giving you precise, real-time insights.
And it’s not just for debugging development builds. The platform is built to monitor performance in your release builds running in production. It helps you uncover issues that only occur on specific devices or under certain conditions; problems that are known as hard to reproduce locally.
The result is faster resolution times, reduced downtime, and smoother user experiences. Your team can ship high-quality Kotlin apps more efficiently and with greater confidence.
The Kotzilla Platform is built specifically for Kotlin developers using Koin, giving you the power to debug and monitor performance across Android and Kotlin Multiplatform apps with confidence.