Monolith vs. Monorepo vs. Multirepo: A Strategic Guide to Repository Choice.
Scaling Frontend Deployments Without Losing Your Mind
The Problem: CI/CD Bottlenecks From a Monolithic Frontend
Imagine this: Your frontend team spends 40 minutes waiting for a pipeline to finish , just to update a label in a modal. That’s not an edge case, it’s the daily grind in many monolithic SPA codebases.
One client we worked with had:
- A single React app with over 1M lines of code.
- 5+ teams pushing to the same repo.
- A build and deploy time of ~35 minutes.
Even worse, a broken dropdown in one feature could block deploys for all teams. CI queues, flaky tests, merged PR chaos. It was clear: the architecture no longer supported the scale.
The Technical Challenge: The Cost of Staying Monolithic
Traditional frontend apps are built around assumptions that don’t age well:
- Shared global state.
- Centralized pipelines.
- Tight coupling between modules.
These choices create friction:
- Long pipelines (avg 30~40 minutes).
- High merge conflict frequency.
- Poor blast-radius control , one bad deploy impacts the whole app.
- Slower onboarding due to massive app context.
This might work for a startup. But once you scale to multiple cross-functional teams, these issues hard-cap your velocity.
Unlocking Scalability with Micro-Frontend Architecture
Instead of treating the UI as a single app, we restructured into discrete frontends.
Each team owned a fully isolated micro-frontend with its own codebase, pipeline, and deploy process:
- Auth
- Dashboard
- Checkout
- Design System
We used Module Federation (Webpack 5) and Single-Spa as the orchestration layer. This allowed apps to be independently built and loaded at runtime.
Some key benefits:
- Parallel development and deploys.
- Targeted rollbacks.
- Team-based ownership.
- Faster feedback loops , some pipelines went from 35 minutes to under 10.
Architectural Blueprint: A Practical Guide
Here’s a simplified architectural layout:
+------------------+
| Shell App |
| (Single-SPA Host)|
+--------+---------+
|
-------------------------------------------------------------
| | | | |
+------+ +--------+ +----------+ +---------+ +--------+
| Auth | | Cart | | Checkout | | Profile | | CMS |
+------+ +--------+ +----------+ +---------+ +--------+
(MF #1) (MF #2) (MF #3) (MF #4) (MF #5)
Each MF (micro-frontend) is a self-contained app. Ownership mapped to the team. Contracts agreed via shared types and interface specs.
Code Snippet: Basic Webpack Module Federation Setup
// webpack.config.js for Checkout app
module.exports = {
name: 'checkout',
exposes: {
'./Widget': './src/Widget.tsx'
},
shared: ['react', 'react-dom']
};
Orchestration handled by Single-SPA
// register apps in shell
registerApplication({
name: 'checkout',
app: () => System.import('checkout/Widget'),
activeWhen: ['/checkout']
});
CI/CD pipelines per app using separate GitHub Actions workflows.
The Results
After adopting micro-frontend architecture:
- Average deploy time dropped from 35 mins to 12 mins.
- Rollbacks became isolated and instant.
- Developer satisfaction scores improved in internal surveys.
- Merge conflict rate decreased by 43% over 6 months.
But it’s not totally free. You need to solve:
- Shared dependencies carefully.
- Error boundaries between apps.
- Loading strategies (preload vs on-demand).
Conclusion
Monolithic frontend architectures eventually reach a breaking point. When every team shares the same repo, pipeline, and deploy , you lose autonomy, speed, and confidence.
Micro-frontends offer a path to decoupling. Done well, they restore ownership and give each team the power to iterate independently.
It’s not always the right call on day one. But if your pipeline times are climbing and coordination is eating your velocity, it’s time to reconsider how your frontend is structured.
Have you hit the limits of your frontend architecture?
Where have micro-frontends helped , or hurt , your team’s flow?
What’s the next evolution after micro-frontends in your roadmap?