
Business Context
Acronis Cyber Protect combined backup, antivirus, and patch management into a single product — but the frontend told a different story. Three separate teams had built three standalone dashboards, each with its own tech stack, design patterns, and deployment pipeline. Users had to context-switch between different UIs to manage their cyber protection, and feature releases were constantly blocked by cross-team dependencies.
Technical Challenge
Unify the three product dashboards into a single cohesive console without stopping feature development. The core challenge was architectural: how do you let three independent teams continue shipping features at their own pace while converging toward a unified user experience? The tradeoffs were between integration speed (faster with tight coupling) and team autonomy (requires loose coupling).
Approach & Decisions
I designed a micro-frontend architecture using Module Federation, where each product team owned a self-contained frontend application that plugged into a shared shell. The shell handled authentication, navigation, theming, and cross-product notifications. I established a shared component library (built on Material-UI) with strict API contracts — teams could use the components but couldn't modify them without going through a design review. One key decision I reconsidered: I initially proposed a shared Redux store for cross-product state, but after modeling the data flows, I realized each product's state was largely independent. I switched to an event bus pattern for the few cross-product interactions (e.g., backup status affecting the security dashboard), which dramatically simplified debugging.
Outcomes
Page load time decreased by 40%, trial sign-ups increased 22%, and task completion rates improved 18%. Each team went from bi-weekly coordinated releases to independent daily deployments. The shared component library reduced UI inconsistencies by 85% across products.
System Design
Key Technical Decisions
Cross-Product State Management
Event bus for cross-product communication, local Redux per product
Shared global Redux store, Shared context providers
Modeling data flows revealed 95% of state was product-local. A shared store would have created tight coupling between teams for minimal benefit. The event bus handled the remaining 5% (status notifications, shared user preferences) with clear boundaries.
Module Federation vs. iframes
Webpack Module Federation
iframes with postMessage, Web Components
iframes would have solved isolation but created UX problems (nested scrolling, inconsistent theming, accessibility issues). Module Federation gave us runtime integration with shared dependencies (React, Material-UI) while keeping build-time isolation.
Shared Component Library Governance
Centralized library with design review gate
Federated contributions, Per-team forks
With 3 teams and no prior shared standards, ungated contributions would have recreated the inconsistency problem. The review gate added ~1 day of latency but prevented UI fragmentation.
Before & After
Deployment Frequency
Coordinated bi-weekly releases requiring all three teams to freeze, test, and deploy together.
Independent daily deployments per team, with the shell updating automatically via Module Federation.
Initial Load Performance
Monolithic bundle loading all three product UIs upfront (~2.8MB).
Shell loads in ~400KB, product modules lazy-loaded on navigation (~300-500KB each).
Want results like these
for your product?
Let's collaborate to build fast, accessible, and high-converting digital experiences that drive real business impact.
Let's Talk
Currently available for select consulting engagements and full-time roles.