In this lesson, you will learn how to architect micro-frontend shared state to prevent cross-module memory leaks and cascading crashes.
When multiple micro-frontends share a global state object in a Node-based host environment, they often fall into a trap: failing to clean up references. If "Module A" subscribes to a global state store but fails to unsubscribe when it crashes or unmounts, the store keeps a reference to that module's scope. This prevents garbage collection, leading to memory leaks that eventually crash your entire host application.
To keep your system resilient, you must treat shared state as a "read-mostly" contract with explicit lifecycle management.
Isolate via Event Bus
Instead of allowing micro-frontends to directly reference a mutable global object, use a decoupled Event Bus pattern. This ensures that if a module crashes, it isn't holding onto shared state objects that the host environment needs to clean up.
// The Event Bus acts as a mediator
const stateBus = new EventEmitter();
// Module A subscribes to updates
const handler = (data) => console.log('State updated:', data);
stateBus.on('state-change', handler);
// CRITICAL: Ensure the module cleans up to prevent leaks
function cleanup() {
stateBus.off('state-change', handler);
}
Defensive Snapshotting
To prevent a "poison pill" module from corrupting shared state, always provide modules with a deep-frozen snapshot of the state rather than a reference to the mutable source. By using Object.freeze() or immutable data structures, you ensure that even if one module attempts to write illegal data to the state, it cannot impact the memory space of other modules or the host itself.
When a module reports an error, the host should force-terminate the module's connection to the bus. Because we used an event-based approach with explicit cleanup, the host can revoke the module's access, allowing the memory occupied by that module's listeners to be reclaimed immediately. This isolation ensures that one module's runtime error remains localized and does not leak into the shared memory of the rest of the ecosystem.
Key Takeaway: Decouple shared state via an event bus and utilize deep-frozen snapshots to ensure that module crashes do not retain memory-leaking references to your application's global state.