The 40-Minute Pipeline: Why Your Build System Is Making You Dumber
Or: How We Measured What Everyone Suspects But Nobody Wants to Talk About
I was having a beer with one of our backend engineers last week. He’s got the CV you’d expect — stints at serious enterprise companies, the kind that have “architecture review boards” and diagrams with more boxes than a distribution warehouse. His CI pipeline takes 40 minutes to complete.
“That’s enormous,” I said, genuinely shocked.
He shrugged. “Joel, we’re a big company with lots of engineers. That’s just what it’s like.”
And there it was — the sentence that should terrify every engineering leader. Not because he’s wrong about big companies having slow pipelines. He’s absolutely right; they do. But because he’s never seen a better way. He’s normalised mediocrity because the alternative has never existed in his experience.
It doesn’t have to be this way.
The Experiment Nobody Wanted to Run
Here at Agoda, we’ve been doing something slightly unhinged: measuring actual developer experience. Not build time as reported by the bundler’s internal telemetry — that self-congratulatory number tools spit out when they’ve finished their work — but the real thing. File change to rendered UI in the browser. The actual wait. The full developer experience.
We built a plugin called devfeedback-js that injects JavaScript into the page from the dev-webserver middleware to measure from the moment you save a file to the moment the UI finishes rendering in your browser. Because here’s the thing: webpack can tell you it compiled in 200ms, but if you’re still staring at a spinner for 25 seconds, who cares what the bundler thinks it did?
We’ve been collecting this data for a year across our frontend systems. The results are uncomfortable, which means they’re probably important.
The Dataset
Before we dive into the numbers, let me give you a sense of what we’re working with. This isn’t a weekend benchmark on a toy project.

That’s over 2.4 million build and HMR events across 629 developers. This is production data from real engineers doing real work over a full year.
And here’s the critical detail that makes this comparison fair: the JavaScript module count in each poly-repo system is roughly equivalent to each module in the modular monolith — approximately 7,000 to 9,000 modules each. We’re not comparing a toy project against an enterprise behemoth. We’re comparing systems of equivalent complexity, architected differently.
The Numbers That Should Keep You Up at Night
Let me show you what we found when comparing our modern poly-repo systems using Vite against our modular monolith using Rspack.

Read that Hot Reload line again. 37 milliseconds versus 912 milliseconds. That’s not a percentage improvement. That’s a different universe of developer experience.
The Developer Experience Gap: HMR Deep Dive
Production builds matter for CI, but hot module reload is where developers actually live. It’s the feedback loop you experience fifty, a hundred, two hundred times a day. Let’s look at the full picture.

Even at P75, Vite developers are getting feedback in under 100 milliseconds. Rspack developers are waiting over a second. The entire distribution is shifted by an order of magnitude.
Why such a dramatic difference? It comes down to architecture. Vite uses native ES modules and only transforms files on demand — when you change a file, it rebuilds just that file and lets the browser’s native module system handle the rest. It’s incremental by design. Rspack, despite being significantly faster than traditional webpack, still follows the bundler model: analyse the dependency graph, determine what’s affected, rebuild that chunk, and ship the result.
For a modular monolith with thousands of interconnected modules, that “determine what’s affected” step becomes expensive. The modular monolith’s modules aren’t truly isolated — they share dependencies, import from each other, and form a web of connections that the bundler must traverse on every change.
The poly-repo systems, by contrast, have hard boundaries. When you change a file in one repo, there’s no possibility it affects another repo’s build. The blast radius is architecturally constrained.
HMR vs Local Full Builds: Where Developers Actually Spend Time
Here’s something the data revealed that I didn’t expect: the ratio of HMR events to full builds tells you a lot about how developers actually work.

Poly-repo developers run roughly equal numbers of full builds and HMR cycles. Modular monolith developers trigger three times as many HMR events per full build.
At first glance, you might think “great, they’re using HMR more!” But consider what this actually means: modular monolith developers are making more iterative changes per “complete” development cycle. They’re also probably afraid to do a full build because it wont be dynamic and takes longer.
When your HMR takes 37ms, rapid iteration is a feature. When it takes nearly a second, that same behaviour becomes a tax — and those 1.6 million HMR events represent a lot of accumulated waiting time.
The Lego Problem
In 2021, researchers at the University of Virginia ran a fascinating experiment. They gave people a Lego structure where a roof was precariously balanced on a single block. The task: stabilize the roof so a figurine underneath wouldn’t get squashed.
The obvious solution? Remove the destabilizing block and rest the roof directly on the wide pillar below.
About 60% of people added more blocks instead.
Even when researchers told participants that adding blocks cost 10 cents each while removing was free, most people still defaulted to addition. They had to explicitly remind participants that “removing pieces is free” before the majority thought to subtract.
The researcher Benjamin Converse explained it like this: “Additive ideas come to mind quickly and easily, but subtractive ideas require more cognitive effort. Because people are often moving fast and working with the first ideas that come to mind, they end up accepting additive solutions without considering subtraction at all.”
Sound familiar? It should. This is your architecture. But how does this relate?
The Values Problem
The difference between teams that choose Vite and teams that choose Rspack isn’t technical capability. Both tools work. Both “compile” JavaScript. Both will get your code into production.
The difference is values in my opinion.
Teams that build small things and keep them simple value simplicity. They value speed. They’ve made a conscious choice that the cognitive overhead of complexity isn’t worth the theoretical flexibility it provides.
Teams that build large, complex things are often the ones looking for an engineering challenge. They’re the brilliant engineers who forget that sometimes the complexity they create with their amazingly engineered solution could have been avoided — or solved by taking things away rather than adding them.
Antoine de Saint-Exupéry, the French aviator and author, understood this a century ago: “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”
He was talking about aircraft design, but he might as well have been describing software architecture.
The Hidden Tax on Your Brain
Let me tell you what even 912 milliseconds of hot reload time actually costs you.
Research from the University of California, Irvine found it takes an average of 23 minutes and 15 seconds to fully regain focus after a significant interruption. Psychologist David Meyer’s work demonstrated that frequent task switching can consume up to 40% of productive time.
But here’s the thing about software development: we’ve normalised constant interruption. We’ve accepted that waiting is part of the job.
In some experiments we did in other repos with dev feedback we saw, it’s at around 20–30 seconds is the threshold where people fully context switch — they check email, browse Slack, make coffee. At 912ms, you’re not going to make coffee. But you’re also not staying in flow. You’re in that uncomfortable middle ground where the wait is just long enough to break your train of thought, but not long enough to do anything useful with.
At 37 milliseconds, you don’t notice the wait. Your change appears before your finger has left the save key. You stay in flow. You keep the entire problem in your head.
What We Actually Learned
After a year of data collection and more lines of SQL than I care to admit, here’s what I believe:
The choice of build tool is a proxy for organisational values. Teams that choose simplicity aren’t less sophisticated — they’re more disciplined. They’ve resisted the temptation to solve problems by adding layers.
The modular monolith is a seductive lie. It promises you can have your cake and eat it too: the convenience of a monorepo with the benefits of modularity. In practice from what Ihave seen, it inherits the worst characteristics of both. You get the coordination overhead of a monolith and the cognitive load of distributed systems thinking, all compiled together into a 2-minute build. Can it ever be good? i think so, but it requires discipline, automation, and a tooling team to support the tool chain you’ll need to run it at good scale, its usual the first point that falls over, because when you are “moving fast” you it’s easier to make compromising and break the module barriers, if those barriers are different git repos, it’s a damn sight harder.
Hot reload time is a better proxy for developer productivity than almost any other metric. It’s the tax you pay on every single change. If you make 50 changes a day and each one costs you 25 seconds of wait time plus a context switch, you’re losing hours daily. Hours that compound into weeks. Weeks that become months of your engineers’ lives spent waiting for computers to catch up.
Complexity is the default. Just like those Lego experimenters, our instinct is to add, not subtract. Building simple systems requires active effort, constant vigilance, and the willingness to say “no” to solutions that feel sophisticated but add accidental complexity.
The Path Forward
I’m not going to tell you to migrate everything in Vite. Rewrites are almost always a mistake — they reset the complexity clock while preserving the organisational dynamics that created the problem. And rspack is making some improvements too (look out for my next blog where I’ll have data from real devs comparing rspack 2 and vite-rolldown).
But I am going to suggest you measure what matters. Not the metrics your tools want to report, but the metrics your developers actually experience. File change to browser render. The real wait.
Because my backend colleague is right about one thing: big companies do have slow pipelines. What he’s wrong about is that this is inevitable. It’s not a law of physics. It’s a choice — a thousand small choices made by people who defaulted to addition when they should have been subtracting.
The next time someone proposes a solution that adds complexity, ask them: “What could we remove instead?”
You might be surprised how often the answer is right there, hiding in plain sight, waiting for someone to notice that the roof would be more stable if we just took away that one unnecessary block.
Now, if you’ll excuse me, I need to go review a PR that adds a new microservice to solve a problem that could probably be fixed with a configuration change. But hey, at least our builds are fast.