Skip to content

3 Ways to Wrangle SaaS Complexity

Posted on:February 20, 2024

This post is inspired from this blog post and also this one.

I originally wrote this in an incredibly spicy, satirical, and cynical tone. Expressing these thoughts in a positive tone was much more difficult, and therefore I thought it merited the effort to do just that. Besides that, I’ve never launched a successful SaaS company so the height of arrogance might be dictating to random strangers on the internet what cardinal SaaS sins to avoid. As such, the following is my take based on my 8 years of experience working as a Software Engineer across many different SaaS products.


Many mistakes made in the infancy of a company are felt for years afterward. Technical mistakes are often paid for one-hundred-fold via engineering salaries and tooling costs. At many companies, I’ve been tasked with fixing these very mistakes. At others, I have been guilty for perpetuating them! I hope my hindsight may help others from making them. I am overwhelmingly convinced that complexity is the ultimate evil that we, as engineers, should be fighting. Generative AI is capable of writing and reading code these days, and while I’m not convinced it’s come for our jobs, I believe we must contend with the value we Software Engineers deliver.

I believe that wrangling complexity is the most important value we offer.

With that in mind, here are 3 Ways to Wrangle SaaS Complexity that Software Engineers (and technically-inclined business owners) should consider:

1. Do not always choose the right tool for the job

We should err towards optimizing for a homogenous architecture, rather than “choosing the right tool for the job”.

Many very intelligent people have said this, and I’m inclined to agree based on my own personal anecdote and the weight of their arguments.

A Ruby on Rails monolith can be scaled to fairly extreme levels with average engineering decisions and discipline. A Node/React SPA can handle a pretty significant amount of traffic before performance becomes the focal point. However, if you split half of your architecture over Ruby, and scatter another half across Node or <whatever language here> you quickly trade technological warts for cognitive load problems. Now, any engineer you bring onboard needs to be able to hold several different points of context in their head to effectively work in your codebase. This will quickly stymie the velocity of an entire engineering organization, as I have unfortunately witnessed on several occasions.

Of course, taken to its logical conclusion, this could yield strange results. We’ll acknowledge that “bad” and “boring” are certainly different things. However, given “average” constraints (which statistically, most companies deal with), we should optimize toward a mature, homogenous, battle-tested stack of technology.

2. Microservices are not (usually) your friend

Microservices, while they have a place, are rarely a good solution for your “We’re replacing spreadsheets” typical SaaS provision. The scale that most companies deal with don’t even come close to justifying the exponential uptick in system complexity. Too-often I have worked on projects that require 4-5 senior level engineers to sit in a room and wrangle with an issue that boiled down to “the way these services interact blew up”. Typically, when reading the postmortem, it would become clear that a monolith would never have run into this. It’s the result of dozens of complex services amplifying their interactions. Datadog even has a tool to identify this exact problem!

In these cases and many more, it costs the company a terrible amount of time and money to “pay” for their complexity. A system simple enough to be reasoned about in your head is cheaper than a system that requires extensive observability tooling. Both in engineering-hours and in tooling costs!

3. Your Software Engineers should also be your Product people

This isn’t meant to take shots at Product Owners or Product Managers. They’re often sharp folks, and many times the functions they serve at extremely large companies is well-justified.

And many times the functions they serve at small to medium-sized SaaS companies is not justified. It’s not because they’re not qualified or capable. In fact, it has nothing to do with “Product” as a business department at all.

I recommend your Software Engineers be your Product People because they are uniquely suited to identifying and solving the problems that plague your customers. Connecting a customer problem with a technical solution is a nuanced task that requires creativity and the ability to connect many dots. In many smaller companies Software Engineers would be more fully utilized (and possibly fulfilled) to be able to execute the whole range of the product lifecycle. Many startups do this by necessity. It’s cheaper. I’d argue it’s also better for the overall effectiveness of the business. At any rate, these tasks can be done when spread between 2 roles. But, as we’ve seen sometimes separating your problem into 2 places just creates 2 problems.


Can you build a successful company by flying contrary to these recommendations?

Of course! Many have.

However, I’ve witnessed many ways that business effectiveness can grind to a halt. Of those ways, the situations where complexity ran rampant seemed to create the hardest course to correct.

I will close with this quote:

It is basically always the case that the long-term costs of keeping a system working reliably vastly exceed any inconveniences you encounter while building it.

And this one too:

Technology for its own sake is snake oil.

Cheers!


Thanks for reading! If you enjoyed this, you may also enjoy following me on twitter!