Given that sharing a dependency as a singleton across microfrontends avoids duplicate downloads and duplicate-instance bugs, under what circumstances would an architect deliberately choose NOT to share a dependency and accept the duplication instead?
answer
- sharing = coordination contract, not free
- stateless utility libs: duplication is cheap
- mid-migration: temporarily un-share
- never co-rendered = no benefit to share
- platform contract vs team autonomy policy
basics
~20 sWhen the cost of duplication (a bit more download size) is smaller than the cost of forcing every team to agree on one version. If teams need to move independently, the library is small, or one team is on an incompatible version on purpose, it's often better to just let it duplicate.
solid answer
~40 sSharing creates a coordination contract -- every consumer of a singleton dependency implicitly agrees to accept whatever version wins negotiation, which reintroduces the cross-team lockstep-release coupling that microfrontends are usually adopted specifically to avoid. An architect skips sharing when: the library is small/stateless enough that duplication's byte cost is negligible (utility libraries under a few KB gzipped); a team genuinely needs to run an incompatible major version temporarily (mid-migration) without blocking or being blocked by siblings; the microfrontends in question are rarely, if ever, loaded on the same page together, so the 'shared instance' benefit never materializes; or the org explicitly wants to preserve per-team autonomy over a specific dependency as a policy, accepting the size cost as the price of that independence.
go deeper
Should have a basic sense that sharing isn't automatically free -- duplicating a small library is sometimes fine.
Should be able to name at least one concrete reason to skip sharing, such as a small stateless utility library.
Should articulate sharing as a coordination/coupling cost and weigh it against duplication's byte cost for a specific scenario, including migration windows.
Should reason at the platform-policy level -- defining which libraries belong in a shared 'platform contract' versus team autonomy, accounting for composition topology and organizational cost of coordination failures, not just per-instance technical trade-offs.
## What sharing actually trades Sharing a dependency as a singleton across microfrontends is not a free optimization -- it trades one cost for another, and a senior architect's job is to recognize when that trade isn't worth making for a particular library or team boundary. - **The benefit side** is well understood: fewer bytes downloaded (only one copy of the library ships instead of N), and for stateful libraries, correctness (avoiding duplicate-instance bugs -- broken context, desynced stores). - **The cost side** is coupling: once several independently deployed microfrontends declare a library as a shared singleton, they have implicitly entered a compatibility contract with each other. Whoever's version 'wins' at runtime becomes the version everyone else must tolerate, and a breaking change by any one team can, depending on strictness settings, either silently degrade (duplicate instance sneaks back in) or hard-break every sibling that depends on the old API. ## Why that coupling matters That coupling is precisely the kind of cross-team lockstep dependency that microfrontend architecture is usually adopted to escape in the first place -- the whole premise is that team A should be able to ship on Tuesday without asking team B's permission. ## Four reasons to accept duplication instead 1. **The cost-benefit math.** The first, most common reason to skip sharing is simply that the cost-benefit math doesn't favor it. A small, stateless utility library -- a date formatter, a validation helper, a set of pure functions with no module-level mutable state -- costs almost nothing to duplicate (a few kilobytes gzipped, sometimes less) and, because it's stateless, carries zero risk of the cross-instance bugs that make singleton sharing worth its coordination cost for something like React. Paying the coordination tax (aligning everyone's semver ranges, testing compatibility, risking a strictVersion failure on deploy) for a library that would cause no correctness problem if duplicated is a bad trade; you're buying negligible byte savings at the cost of real deployment coupling. 2. **A migration window.** A second reason is deliberate, temporary divergence during a migration. If one team is mid-migration from a major version of a framework or library to the next -- say, moving off an old state-management library while siblings are still on the current one -- forcing that library to remain a shared singleton either blocks the migrating team from starting until everyone else is ready, or blocks everyone else from their normal releases while the migration is in flight (depending on which direction the incompatibility points and how strict the version policy is). Explicitly un-sharing that dependency during the migration window lets the migrating team run their new version in isolation, duplicated, without either side blocking the other; the size cost is temporary and acceptable, and it's re-shared once the migration completes across all teams. 3. **Composition topology.** A third reason is that the 'singleton' benefit never materializes for microfrontends that are, in practice, rarely or never composed on the same page together. If microfrontend A only ever renders on one route and microfrontend B only ever renders on a completely different route, and no page composes both simultaneously, there is no actual runtime instance to deduplicate -- the browser only ever loads one of them per page view anyway. Configuring them to share a singleton in that case adds negotiation complexity and coupling risk for a benefit that never actually occurs, since they're never on the same page. This is a case where understanding the platform's actual composition topology, not just its dependency graph, should drive the sharing decision. 4. **A deliberate autonomy policy.** A fourth, more organizational reason is a deliberate autonomy policy: some platforms explicitly decide that certain libraries -- often anything outside a small, centrally governed 'platform contract' of framework/router/design-system -- are simply never shared, on principle, so that no team is ever blocked by another team's choice of library version for anything outside that contract. This trades a knowable, bounded byte cost (bounded because the org can audit and cap how many such libraries exist) for a hard guarantee of deployment independence beyond the platform contract, which is often judged worth it precisely because coordination failures are harder to detect and more expensive to unwind than a slightly larger bundle. ## The two failure modes in production - In production, **over-sharing** (sharing when you should have accepted duplication) looks like exactly what's covered under the coupling and version-negotiation questions: teams blocked on each other's release schedules, or silent duplicate-instance bugs from fallback resolution. - **Under-sharing** (duplicating when you should have shared) is the failure mode that is more mundane but still real: noticeably larger page weight from redundant framework code across several microfrontends on one page, showing up as a bundle-size regression that traces back to, say, five microfrontends each bundling their own 45KB copy of React because nobody configured the shared scope. That second one is a bug of omission rather than a deliberate trade-off, and the reason architects need a stated policy (which libraries are platform-contract singletons, which are intentionally left autonomous) rather than leaving the choice ad hoc per team.
- Why might sharing a dependency be pointless even for two microfrontends that are perfectly version-compatible?If those two microfrontends are never actually rendered together on the same page in real usage -- say, one only appears on a checkout flow and the other only in an admin dashboard -- there's never a runtime moment where a single shared instance would actually be reused. The negotiation and coupling machinery adds complexity for a deduplication benefit that never occurs in practice.
- How should an architect decide which libraries belong in a 'platform contract' of always-shared singletons versus which are left to team autonomy?Typically by weighing statefulness (does the library hold shared, page-wide state that breaks with duplication?) against size (is duplication's byte cost material?) and composition topology (do the teams' microfrontends actually co-render often?) -- libraries that are stateful, large, and frequently co-rendered belong in the shared contract; small, stateless, or rarely-co-rendered libraries are better left to team autonomy, with the boundary documented and periodically revisited rather than decided ad hoc per team.
- What's the practical downside of forcing a library to stay a shared singleton during a major-version migration that only one team is currently doing?It creates a blocking dependency between the migrating team and every other team sharing that singleton: either the migration can't start until everyone else is ready to move together, or (if pushed through) it breaks every sibling still on the old API. Temporarily un-sharing the dependency lets the migration proceed in isolation, at the cost of a temporary size duplication that's removed once migration completes.
It's like deciding whether neighboring shops in a mall should share one delivery truck. If they all sell perishable goods needing the exact same schedule, sharing saves money. But if one shop is mid-renovation and needs deliveries at odd hours, or two shops never actually get customers at the same time of day, forcing them onto one shared truck schedule just to save a bit of fuel creates more scheduling conflict than it's worth.
saying these in an interview costs you the question
- Treats sharing as an unconditional best practice with no downside
- Can't name a single concrete scenario where duplication is the better choice
- Ignores composition topology (whether apps are ever actually co-rendered) when reasoning about sharing
- Doesn't recognize sharing as a form of cross-team coupling
- Has no answer for how to handle a migration under a strict singleton policy