F2F #89: The case for underengineering

F2F #89: The case for underengineering

Photo by Ronin / Unsplash

A few weeks ago I sat down with Alberto Betella, the owner of RSS.com for the MarsBased podcast. At some point, we were discussing architectural decisions, and how barebones the first versions of his software were, barely a few lines of php. No fancy containers, no load balancers, no bloated frontends, no nothing. RSS.com is fully bootstrapped, so every line of unnecessary code costs real money, meanwhile, their VC-backed competitors were shipping features nobody asked for, running teams twice the size, and somehow moving slower.

When I posted the episode on LinkedIn, I came up with the word "underengineering" (which, apparently, is barely used in certain circles so I can't claim it) and it got a few eyebrows raised and positive reactions overall, so I've been reflecting on it ever since.

Underengineering is not a lack of craft. It is a deliberate decision to build only what the problem actually requires, and nothing more - or even less, momentarily, because you can afford. It is the opposite of overengineering: no speculative abstractions, no infrastructure for scale you have not reached yet, no features added because you had the budget to add them, no "I know I will need this someday", no nonsense. It sounds obvious but it is surprisingly rare, in software engineering.

The reason it is rare is that building more feels like progress. Or, simply put, not building enough feels like you're leaving money on the table because it feels like a missed opportunity.

When you are flush with cash, in the case of VC-backed companies, adding a feature is easy to justify. You're running against time (and money), so you have to try lots of things to see which one takes off. When you have engineers sitting idle, letting them build something complex looks better than admitting there is nothing worth building right now. And don't get me started on fixing technical debt.

VC-backed companies especially fall into this trap. They have the money, they have the people, and they have the impending pressure of building because the sensation of movement feels like progress, even if they're not headed in the right direction, so they overbuild.

But this also happens to indie developers, small companies and bootstrapped startups. It doesn't only boil down to having too much money in the bank. It is oftentimes a matter of seniority.

“If I had had more time, I would have written a shorter letter” - Blaise Pascal

I remember I indulged in overengineering every time I learned a new programming concept, I wanted to try it. Ternary operator in Java? Let me try it and prove I know things, making it harder for others to learn my nonsense code! But they have to know that I know this thing.

Curiously, we never indulge in underengineering. Never ever. It's like admitting that you don't want to do your job.

AI has changed the math

Here is what makes this more urgent today: AI has effectively eliminated the cost of building software. A solo founder with no engineering background can now ship a "working" product in a weekend. Allegedly. A small team that used to need six months to get to an MVP can do it now in six weeks. The real challenge now is in the distribution phase, not in developing.

This means dev proficiency is no longer a moat. If building is cheap for you, it is cheap for everyone, and chances are that there are more people smarter than you out there. The founders who win now are not the ones who can build the most sophisticated thing but those who can get their thing in front of the right people, at the right time, make them care about it, and convert that attention into something durable.

Distribution is the hard part now. It always was, but we had a convenient excuse to look away from it: we were too busy building so we left that to marketers and other profiles. That excuse is now gone, so we have to do it ourselves now because AI tools are building our products.

So if you are spending six months on features when you have no users, you are not working on a technical problem: you are avoiding a harder one. Every hour overengineering is an hour not spent finding out whether anyone actually gives a flying fuck about what you are making.

What underengineering looks like in practice

Underengineering, actually, means shipping the version that barely works before shipping the version that scales. It means choosing boring technology that you know inside out over exciting technology that requires even the slightest bit of onboarding. It means running a barebones app for too long to the point where it's painful for you. It means writing a cheap and dirty two-files php application to get off the ground. One, if possible. Pieter Levels famously runs such applications and he's somewhat successful. Maybe someone else could do it too.

At MarsBased we have run this way since the beginning. When we had the chops and the money to build a great website, we decided to build a quick wordpress and that was our website for the first two years. We also could've created a great app to register for a private slack community we had for startups in Barcelona but we just integrated a typeform with stripe payments and that was it. We had it for seven years, because we decided to place our fucks somewhere else: where it mattered.

Instead of asking "should I build this?", you should be asking "is it the right time to build this?", but it's a harder question, and a more uncomfortable one, too.

The RSS.com conversation reminded me that underengineering is not a consolation prize for companies that cannot afford to do more but it is a discipline. It is part of the culture, too.

The real question right now: If AI can build the thing you want to build, what is your actual edge?