Simple beats clever

Complexity looks smart. Usually it's hiding cost and fragility. Why I choose Rails over React, Stimulus over frontend frameworks, and simplicity over sophistication.

Complexity looks smart. Usually it's hiding something.

Cost. Fragility. Risk you won't see until it's expensive. I've watched teams drown in systems that only their creators understood. I've inherited codebases where "clever" meant "unmaintainable." I've seen startups burn runway on architecture they didn't need.

I have a low tolerance for unnecessary complexity. Not because I can't handle it. Because I've learned what it actually costs.


Why I choose Rails over React

This site runs on Rails. Server-rendered HTML. ERB templates. No build step for the frontend. No webpack. No node_modules folder with 847 dependencies.

I could have built it as a React SPA with Next.js. That's what most developers would reach for in 2025. It's what job postings ask for. It's what bootcamps teach.

But here's what a React frontend actually means:

For what? Slightly smoother page transitions?

Rails gives me conventions. One way to do things. A twenty-year ecosystem of solved problems. When I pick up a Rails project, I know where everything is. Models here. Controllers there. Views in the obvious place.

React projects are different every time. This one uses Redux. That one uses Zustand. This one has the API calls in hooks. That one has them in a services folder. Every team reinvents the wheel and calls it "architecture."

Convention over configuration isn't just a slogan. It's the difference between building features and debating folder structure.


Why I choose Stimulus over frontend frameworks

This site has interactive elements. Dropdowns. Toggles. Mobile navigation. Scroll animations.

All of it runs on Stimulus. A few hundred lines of JavaScript total.

Stimulus doesn't try to own the page. It enhances HTML that's already there. The markup is readable. The behavior is obvious. A new developer can look at data-controller="dropdown" and understand what's happening.

Compare that to a React component tree. Props drilling through five layers. Context providers wrapping everything. useEffect hooks with dependency arrays that break in subtle ways. State that lives in three different places.

I'm not saying React is bad. I'm saying it's a lot of machinery for problems most sites don't have.

Stimulus lets me write JavaScript like it's 2010 — except better organized. I add interactivity where I need it. The rest is just HTML. There's nothing to compile. Nothing to bundle. The browser runs it directly.

That's not primitive. That's leverage.


The Monday.com example

I do a lot of work with Monday.com. Not because it's the most powerful platform. Because it's the most practical.

A client comes to me wanting a CRM. The enterprise answer is Salesforce. Six-figure implementation. Months of configuration. A consultant class that exists solely to manage the complexity.

Monday.com does 80% of what Salesforce does. A small team can build it themselves. When requirements change, they can change it themselves. No ticket to IT. No waiting for the next sprint.

Is it as powerful? No. Is it powerful enough? Almost always.

I'd rather give a client a system they can own than one they depend on me to maintain. That's not just good ethics. It's good business. They come back for the next problem because I solved the first one without creating a dependency.


When complexity is warranted

I'm not dogmatic about this. Some problems require complex solutions.

High-frequency trading systems. Real-time collaboration at scale. Machine learning pipelines. These have inherent complexity that can't be simplified away.

But most software isn't that. Most software is forms and lists and dashboards and workflows. CRUD with business rules. The kind of thing Rails was built for.

The question isn't "is this complex?" It's "does the complexity produce net leverage?"

If the complexity solves a real problem and the team can maintain it, fine. If it's there because someone wanted to use a new framework or pad their resume, that's technical debt disguised as innovation.


The real cost

Complexity compounds. Every abstraction you add is a decision future developers have to understand. Every library is a dependency that will eventually break. Every clever pattern is a training burden for the next hire.

Simple systems are debuggable. When something breaks, you can find it. You can fix it. You can explain to the client what happened.

Clever systems are fragile. They work until they don't. And when they don't, you're reading stack traces through five layers of indirection, wondering what the original author was thinking.

I've been on both sides. I'll take simple every time.


The test

If you can't explain it clearly, it's probably doing too much.

That's not a platitude. It's a diagnostic. When I'm building something and I can't explain it simply, that's a signal. I'm either solving the wrong problem or solving it the wrong way.

Simple doesn't mean easy. Simple is the result of doing the hard work to understand what actually matters and cutting everything else.

Simple is a choice. And it's the one I keep making.

Share this article
LinkedIn Facebook X