Download EPUB

The Paradox of Fancy Tooling

fagnerbrack.com 4 min read Original article
Summary
A good carpenter does more with a simple hammer than a chainsaw-shaped one. Opinionated software frameworks work the same way: they raise the floor for weak engineers but lower the ceiling, trapping strong ones who hit limits the authors never planned for.

JavaScript won the web despite rushed design and loose typing, mainly because of first-class functions. That one simple primitive let engineers build things its designers never imagined. Java shipped the same year with class hierarchies and fixed web conventions that were wrong for most apps, so escaping meant leaving the ecosystem.

Heavy frameworks let weak engineers ship "good enough" quickly, but the cost shows up at the first deviation, when you need something the tool will not give you. Teams measure days to first demo when the number that matters is days to first deviation.

The Paradox of Fancy Tooling

Plain hammer beside an over-built chainsaw-hammer, showing simpler tools reward skill

A good carpenter does a lot with a good hammer. Hand the same carpenter a hammer shaped like a chainsaw and the work gets worse and slower, not better or faster. The grip fights the hand. The weight sits wrong. The tool does more than a hammer needs to, and does very badly the one thing a hammer is for.

Most software tooling tends to drift towards a chainsaw-shaped hammer.

Frameworks arrive with routing, state management, auth scaffolding, a build pipeline, and a strong opinion about where your files go. A developer who has not read the HTTP spec can ship a working API on top of it in a weekend. The demo runs, the reviewer sees behavior and approves.

That looks like progress but I don’t think it is — at least not the kind that compounds the value.

Here is the paradox: Opinionated tooling raises the floor and lowers the ceiling in one single move. A framework carries a weak engineer past the parts they have not learned yet, so the floor rises and they don't learn anything. The ceiling comes down later, when the work runs into a context, often specific to the domain you apply the framework, that the authors did not forsee. Step outside that domain-specific context and the wall is no longer yours, it belongs to whoever wrote the framework and they won't be around to help you fix the issue.

A strong engineer hits that wall and starts fighting the tool, sometimes looking at the source code and spending more time on that than getting the job done. They read the framework’s internals and write a workaround that feels like a hack. The weekend the framework saved a junior costs a week to the senior, and the senior is the one who pays the cost.

The framework that carries a weak engineer is the same framework that traps a strong one.

Tools without opinions don’t behave this way. They hand you primitives and step back, giving you the power to createon your own terms!

I’ve worked in JavaScript for most of my career of 20 years, including years co-maintaining a small open-source library that millions of sites still load. JavaScript is not a well-designed language, the first prototype of JS was built in about ten days in 1995, and the quirks from that rush sit in the language today. However, JS won anyway… One decision explains most of that:

First-class Functions

Yes. A first-class function is the basic hammer. You hold a function the same way you hold a number or a string. You can pass it into another function or hand one back.

Callbacks, event handlers, middleware, reducers: all of it comes from that one idea. The language gave you a small construct with almost nothing attached, then stepped out of the way. YOU hold the power to create.

So a language with no module system at the start, loose typing, and equality rules people still laugh about became the one running on nearly every site on the web, even on back-end with NodeJS. The construct underneath was simple/powerful/basic, whatever you call it, and engineers who understood it built things its designers had not planned for. Of course, the ones who didn't created a mess but they became the seniors to fix it later anyway.

The languages it competed with made the opposite trade. Java shipped the same year with class hierarchies, deep inheritance, and configuration you wrote by hand. Its enterprise stack had a fixed idea of how a web application should be shaped. For most applications that idea was wrong, and escaping it meant leaving the ecosystem behind and building everything from scratch by yourself. Good luck on that..

That is the trap with rich tooling. It does a lot of things, and it does few of them in a way you can bend to a given context on the company stage/domain/skillset.

I have watched this play out more than once. A change that takes an afternoon on plain tools turns into a week on the framework, since the framework has to be worked around first.

Would the afternoon change be "technically" better? Probably not, but it's the right solution often times when the "technically better" is over-engineering.

A weak engineer can reach “good enough” on a heavy framework. The framework already made the hard calls for them. The output ships, and it can look consistent next to the work of stronger people.

The cost does not show up in the demo. It surfaces later, the first time the product needs something the framework was not built for. Does any of this mean frameworks are a mistake? No. It means most teams measure them wrong.

They count the days to the first demo. The number that matters is the days to the first deviation, the first time you need something the tool will not hand you.

That is when you find out what you really bought yourself into.

It's 2026. Sounds familiar?

If you liked this, you might like Readplace, built for exactly this kind of reading.

Thanks for reading. If you have some feedback, reach out to me on LinkedIn, Reddit or by replying to this post.