App Instrumentation Optimization: Sending Analytics to Multiple Frameworks in Multi-Module Environment

Android Dec 29, 2023

At Halodoc, we place a high emphasis on delivering top-notch code quality, optimisation, and maintaining robust architecture across all our projects. Our commitment extends beyond mere functionality, focusing on the long-term sustainability and scalability of the codebase.

In modern Android development, analytics play a crucial role in understanding user behaviour and improving app performance. In a multi-module environment, optimising the instrumentation for sending analytics to multiple frameworks becomes essential for maintaining a clean and efficient codebase.

Overview of Nias

The Nias module serves as a central hub for handling analytics events and user properties across multiple plugins within our Android applications. It acts as a bridge that connects various analytics frameworks, allowing seamless integration and communication.

Key Responsibilities of the Nias

  1. Frameworks Registration: The Nias module is responsible for registering and managing various analytics frameworks used in our applications.
  2. Event Handling: It facilitates the handling of different types of analytics events and ensures their proper dispatching to the registered plugins.
  3. User Information: The Nias module manages user information and provides a standardized approach for updating and syncing these information across analytics frameworks.

Here is the Earlier Analytics Integration Flow

Key Challenges of Nias

1. Module Independence

In the earlier stages of our plugin development with Nias, overriding functions and handling user properties involved a sequence of IF conditions. The Nias module checked events based on the presence of key values, and if conditions were met, the HashMap values were accessed to trigger user property events for a specific plugin.

‌This approach, while functional, had its drawbacks. The UserProperties class was confined to the Nias module, resulting in a dependency whenever other modules wanted to send user properties. Adding new user properties required modifications to the Nias module, creating an undesired inter-module dependency.

2. Multiple Analytics Frameworks

The current implementation showcases a broad approach to user properties and events handling. Here's a snippet

‌‌While the existing code accomplishes its goal, it performs additional checks and broadcasts user property events to all plugins, irrespective of the intended recipients. This leads to extended compilation times, increased runtime overhead.

Here is the initial Event type

‌The challenge emerged when certain events were ambiguously associated with multiple analytics frameworks





The approach of mapping multiple analytics frameworks to one or more event types posed a challenge in determining which analytics framework a particular event type should be routed to.‌‌‌‌ Initially, the codebase utilized an EventType  of EventFilter to define various event types.

Hence, Plugin registration required ambiguous Event types like below

‌‌Optimizing User Property Events in Multi-Plugin Environments: A Strategic Approach

In the pursuit of enhancing the efficiency of our analytics module, we've devised a streamlined solution that optimizes the handling of user property events within a multi-plugin environment. Let's delve into the key aspects of our optimized approach

1. Introducing Plugin Types

To facilitate targeted event dispatching, we have introduced a list of plugin types. Each module, when relaying user property information, will include this plugin types as a list. If no list of plugin types is provided, the event will be sent to ALL registered plugins. Here's a glimpse of the plugin types

enum class Plugins {

‌Upon introducing a new Enum named Plugins, numerous lines of code associated with the previous Event Type and EventFilter in all modules were successfully removed.

2. Efficient Event Dispatching

Our refined code ensures that user property events are dispatched only to the necessary plugins. The method sendAnalyticsData handles this process, accepting the event and a list of required plugins. This approach eliminates the need for cumbersome IF conditions inside Analytics Framework for checking key values, providing a cleaner and more efficient solution.

The isRequiredPlugin method efficiently checks if a specific plugin is required based on the provided list of plugin types. The inclusion of the Plugins.ALL option allows events to be directed to all registered plugins, simplifying the control flow.

3. Granular Control with Plugin Types

In our pursuit of refining event dispatching, the introduction of Plugin Types provides granular control over the analytics framework selection for user property events. This streamlined approach eliminates the previous need for mapping multiple analytics frameworks to one or more event types. Now, events can be precisely directed to specific analytics frameworks or broadcasted to all. The utilization of Plugin Types enhances code readability and simplifies the control flow. For instance

Sending Events to Amplitude and Braze

Nias.trackEvent(EventName, information, NiasUtils.setPluginList(Plugins.AMPLITUDE, Plugins.BRAZE))

Sending Events to All Registered Plugins

Nias.trackEvent(EventName, information, NiasUtils.setPluginList(Plugins.ALL))

4. Seamless Migration

To ensure a smooth transition, we've maintained existing override functions for the potential triggering of events from various modules in different flows. New overriding functions have been introduced, gradually transitioning existing ones. This systematic migration process ensures organized code maintenance and helped to release the changes incrementally.

Our step-by-step optimization approach guarantees a more efficient and scalable analytics module. By embracing targeted event dispatching and strategic enum usage.

Here is the Streamlined Analytics Integration Flow

‌‌Benefits of Current Implementation

1. Code Simplicity and Readability

The introduction of Plugin Enums streamlined the codebase, reducing unnecessary complexity. This resulted in improved readability, making it easier for developers to understand and maintain the analytics infrastructure.

2. Enhanced Maintainability

Centralizing plugin-related logic through Plugin Enums contributed to a more maintainable system. Modules became independent of EventType checks, simplifying future updates and modifications.

3. Efficient Compilation and Runtime

The removal of additional checks for all plugins, as seen in the previous implementation, led to faster compilation times and reduced runtime overhead. This optimization positively impacted the overall performance of the application.

4. Reduced Application Size

By dispatching user property events only to the necessary plugins and removing existing analytics codes used without any Event Type across all modules, the application size was minimized, resulting in a reduction of up to 300kb. This size reduction is crucial for improving app efficiency and ensuring a smoother user experience.

5. Improved Scalability

The optimized approach, driven by Plugin Enums, enhances the scalability of the analytics module. Adding new plugins or making changes to existing ones can now be done seamlessly without affecting other modules.

6. Clearer Event Routing

The transition from ambiguous EventType associations to a more strategic Plugin Enum approach provides clarity in event routing. It is now easier to determine which analytics framework should receive a particular event type, reducing ambiguity.


The transformation from a complex EventType system to a streamlined Plugin Enum model signifies a commitment to elevating code quality and optimization at Halodoc. This strategic pivot not only overcame existing challenges but also paved the way for an analytics module that is more efficient, scalable, and easier to maintain within our multi-plugin environment.

In addition to resolving previous hurdles, the revamped approach to sending user property events to analytics frameworks introduces simplicity and enhances readability for developers. By fostering module independence, this optimization ensures a more modular and adaptable architecture. In the broader context of enhanced analytics frameworks sets the stage for integrating new analytics tools seamlessly

This optimized approach serves as a testament to our dedication to delivering top-notch Android applications with a focus on both functionality and code excellence.


Join Us

Scalability, reliability and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels and if solving hard problems with challenging requirements is your forte, please reach out to us with your resume at

About Halodoc

Halodoc is the number 1 all around Healthcare application in Indonesia. Our mission is to simplify and bring quality healthcare across Indonesia, from Sabang to Merauke. We connect 20,000+ doctors with patients in need through our Tele-consultation service. We partner with 3500+ pharmacies in 100+ cities to bring medicine to your doorstep. We've also partnered with Indonesia's largest lab provider to provide lab home services, and to top it off we have recently launched a premium appointment service that partners with 500+ hospitals that allow patients to book a doctor appointment inside our application. We are extremely fortunate to be trusted by our investors, such as the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek, and many more. We recently closed our Series D round and in total have raised around USD$100+ million for our mission. Our team works tirelessly to make sure that we create the best healthcare solution personalised for all of our patient's needs, and are continuously on a path to simplify healthcare for Indonesia.

Mayur Hebbar

Android Developer