Tech/Engineering

From Monolith to Multi-Level Microfrontends: How Druva Built Scalable UIs

Roshni Devadiga , Principal Engineer, Enterprise Workload

Building a feature-rich, maintainable user interface is one of the most pressing challenges for engineering teams today. As applications scale, monolithic codebases often obstruct progress, slowing down innovation and increasing complexity. This was the exact obstacle we encountered with our Enterprise Workloads UI. This blog post shares our journey from a cumbersome monolith to a scalable, multi-level microfrontend architecture.

The Problem: The Monolithic Monster

As our Enterprise Workloads UI evolved, its monolithic codebase became increasingly difficult to manage. This led to several key challenges that will sound familiar to many developers:

  • High Maintenance Overhead: The single, large codebase was difficult to understand, maintain, and extend.

  • Painful Dependency Upgrades: Upgrading any package often introduces breaking changes across the application, requiring extensive and time-consuming fixes.

  • Tightly Coupled Components: Changes in one part of the application frequently had unintended consequences in others, leading to lengthy and repetitive regression testing cycles.

  • Unmanageable Build Times: The sheer size of the application resulted in slow build and deployment processes, delaying the release of new features.

  • Slow Testing Cycles: The time it took to run unit and component tests increased significantly, impacting developer productivity and feedback loops.

What are Microfrontends and Why Should You Care?

To address these challenges, we turned to a microfrontend architecture. So, what is it?

A microfrontend architecture is a design approach where a front-end application is decomposed into individual, semi-independent “micro-apps” that work together. This approach brings the same flexibility and speed to front-end development as microservices provide for back-end teams.

Here’s a simple visual representation of the shift from a monolithic to a microfrontend architecture:

Monolithic vs. Microfrontend Architecture

Monolithic vs. Microfrontend Architecture

The primary benefits of this approach are:

  • Independent Development: Different teams or team members can work simultaneously on different parts of the application, without interfering.

  • Separation of Concerns: A critical advantage is fault isolation. A bug or runtime error in one microfrontend is contained within that specific section. This prevents a single point of failure from crashing the entire application, leading to a more robust and resilient user experience.

  • Consistency and Reusability: It becomes easier to create and share common components (like headers, footers, or sidebars) across different products, ensuring a consistent user experience.

  • Faster Testing Cycles: When a change is made to a specific microfrontend, only its dedicated test suite needs to be run, rather than the tests for the entire application. This dramatic reduction in testing time means developers can iterate more quickly, merge code more confidently, and ultimately ship features faster.

The First Step: A New Set of Challenges

Our initial strategy was to develop any new workloads as independent microfrontends. We used a technology called Webpack Module Federation to enable this modularity. Module Federation allows different, independently deployed front-end applications to dynamically share and consume code at runtime. Each microfrontend publishes a remoteEntry.js file, which acts as a manifest, listing the components and functions it's willing to share.

While this approach helped with scalability, it introduced a new set of problems:

  • Duplication of Code: Each new microfrontend needed its own copy of common utilities, components, and shared modules, leading to redundancy and inconsistencies.

  • Increased Complexity in Data Flow: The main application had to pass down multiple parameters (like user permissions, environment configurations, etc.) to each microfrontend, making integration complex and cumbersome.

  • Static and Brittle Configurations: A standard Module Federation setup requires remote URLs to be hard-coded in the configuration. This was not a viable solution for us, as our application needed to run across multiple deployments and environments, each with different URLs

Our Solution: A Two-Part Strategy for a Scalable Frontend

To overcome these challenges, we adopted a strategy that addressed both our architecture and deployment process.

Part 1: A Multi-Level Microfrontend Architecture

To overcome these new challenges, we adopted a multi-level microfrontend architecture. This approach introduces three distinct levels of microfrontends, each with a specific purpose.

The Multi-Level Microfrontend Architecture

 

Multi-Level Microfrontend Architecture

Here’s how the layers work:

  1. Level 1: The Common Utility Microfrontend This foundational layer contains utility functions, helper methods, and other low-level abstractions that can be used across all other microfrontends. This includes dates/time utilities, API request handlers, and formatting functions. By centralizing these, we eliminate code duplication and ensure that all microfrontends use the same logic for common tasks.

  2. Level 2: The Core Components Microfrontend This layer houses common UI components and shared business logic that multiple workloads depend on. A good example is a specialized list component that encapsulates the business logic for API calls and user interactions. Instead of each workload team building their own list component, they can import it directly from this shared microfrontend, ensuring consistency and saving development time.

  3. Level 3: The Workload Microfrontends Each business function or "workload" is developed as a separate microfrontend at this top level. These microfrontends are the consumers of the two lower-level microfrontends. They use the utility functions from the first level, and the UI components and business logic from the second level as building blocks. On top of this, they add their own functionalities to create the UI for their respective workload management sections.

Part 2: Dynamic Module Federation for Flexible Deployments

One of the most powerful features of our new architecture is the use of dynamic module federation. In a typical setup, the URLs of the remote microfrontends are hard-coded in the configuration. However, this is not ideal for enterprise applications deployed in multiple environments (e.g. development, staging, production), where the URLs will be different. Also with “hydra” (an internal initiative of multi deployment), even in the same environment, we can have multiple deployments (eg: deployment for multiple regions).

With dynamic module federation, we can load the URLs of the microfrontends at runtime. This means we can build our application once and deploy it anywhere, with the application dynamically discovering and loading the correct microfrontends for that specific environment. This provides huge flexibility and simplifies our deployment process.

Quantifiable Improvements in Scalability and Performance:

Beyond theoretical benefits, our microfrontend adoption has yielded concrete, measurable gains in scalability and performance:

Accelerated Build Times: Our microfrontend builds now complete in approximately less than 5 minutes, a dramatic reduction from the previously unmanageable build times of our monolith. This significant reduction in build time directly translates to faster iteration cycles and quicker deployment of new features.

Enhanced UI Load Times: By leveraging CloudFront for rendering microfrontend bundles, we've achieved load times in milliseconds. The benefits of edge location caching have made the UI significantly more responsive and performant for our users.

50% Increase in Development Velocity: The abstraction and modularization of business logic and UI for common components within the Core Components Microfrontend have led to a 50% increase in development velocity. This allows our teams to rapidly develop new workloads by utilizing pre-built, standardized building blocks, greatly speeding up the time-to-market for new features.

Improved Testing Cycles: The initial challenge of "slow testing cycles" has been effectively addressed. Our current microfrontend setup has led to improved Component Tests running times, further accelerating developer feedback loops and enhancing code quality.

Unique Architectural Alignments for a Seamless Transition:

Druva's multi-level microfrontend approach goes beyond a simple technical migration; it represents a strategic alignment with our core architectural principles. This alignment has greatly streamlined and simplified the transition process.

Mirroring the 'Unity' Framework: Our back-end teams had already embraced a 'Unity' framework, which streamlined much of the repetitive work at the backup set and job level that various workloads and teams used to handle. This approach of abstraction, modularization, and reusability became a foundational part of Druva's engineering DNA, enabling greater efficiency and consistency across teams.

Our multi-level microfrontend architecture mirrors this successful back-end strategy on the UI side. This alignment provided a significant advantage, as it allowed us to extend our architectural philosophy naturally to the front end. The shift from a monolith to an advanced, multi-level microfrontend setup became a smooth evolution, simplifying the process while maintaining consistency in our design principles.

Conclusion

Transitioning from a monolithic UI to a multi-level microfrontend architecture has been a game-changer for our team at Druva. By breaking our application into smaller, reusable, and independently deployable components, we’ve dramatically enhanced our development speed, scalability, and maintainability.

This structured, layered approach has enabled us to fully leverage the advantages of microfrontends while avoiding common challenges like code duplication and overly complex data flows. If your monolithic front-end is holding you back, we strongly encourage exploring this transformative approach.