Communication Between Micro-frontends
Note from the N-iX interview prep â micro-frontend architecture.
In a micro-frontend architecture, each MFE is an independently deployable application. They need to communicate without tight coupling. There are two primary patterns.
1. Event Bus (Pub-Sub)
- How it works: MFEs publish and subscribe to events via a global event bus
(e.g., using
window.dispatchEvent+addEventListener, or a library likemittorEventEmitter). - When to use: For loosely coupled, broadcast-style communication â e.g., âuser logged inâ, âcart updatedâ, âtheme changedâ.
- Pros: Decoupled, easy to add new listeners without modifying senders.
- Cons: Harder to debug (events fire and forget), no type safety by default.
// MFE A â publishes an event
window.dispatchEvent(new CustomEvent("user:logout"));
// MFE B â listens for the event
window.addEventListener("user:logout", () => {
// clear session, redirect, etc.
});
2. Shared State (Global Store)
- How it works: MFEs share a single, centralized state (e.g., Redux, Zustand, or a simple observable object) that lives in the container/shell app.
- When to use: For data that multiple MFEs need to read/write consistently â e.g., user profile, shopping cart, feature flags.
- Pros: Predictable, type-safe, easier to debug (DevTools), single source of truth.
- Cons: Couples MFEs to the store contract; changes to state shape affect all consumers.
// Shared store (defined in the container)
const useStore = create((set) => ({
user: null,
setUser: (user) => set({ user }),
}));
// MFE A â sets the user
useStore.getState().setUser(loggedInUser);
// MFE B â reads the user
const user = useStore((state) => state.user);
My Approach (Real-World)
In Seguralta, we combined both patterns:
- Shared Redux store for application-wide data (user session, feature flags, tenant config).
- Event bus for UI-level interactions (âopen modalâ, ârefresh dashboardâ, âtoast notificationâ) â they didnât need to persist in state and we didnât want to pollute the store.
Key Considerations
- Versioning: If the shared state contract changes, all MFEs need to update â see shared library versioning.
- Lazy Loading: Avoid importing the entire store into every MFE â use selective slices. Related: code-splitting.
- Testing: Both patterns are testable; event bus requires spying on events, shared state can be mocked easily.
Back to the index: N-iX â Interview Prep.