Some seem to treat microservices as a sign of good engineering when it's often just premature complexity. You can always split a monolith later, but you're stuck maintaining that complexity from day one

I have been building a SaaS for a business. One of the decisions I took is "as monolithic as possible" (though you cannot just use that).

One reason is that microservice architecture requires much more operational overhead. So any server we have (except for the database) should be self-contained as a rule, so that it can be autonomous and horizontally scalable.

So far, it is working quite well. You do not need suddenly a Redis for one thing, a ZooKeeper for the next one, and 3 or 4 things to just run the damn binaries. The binaries will start, do whatever migrations need to be done if it applies, and start running. They only need the database. They land health checks, api calls and all the logic needed, in one binary with zero dependencies that is containerized.

This has saved me a lot of pain compared to other architectures where I worked, but those were massive and it was justified (and there was budget for it). But you just need a bunch of teams to be able to do that.

I think going the microservices way for a small team not only does not pay off. I think it can be a suicide.

At the same time, I keep the servers internally modular (enable/disable feature).

With microservices they're obviously complicated, and that's better. There's a complexity in monoliths as well, but it's hidden complexity. That gives developers a false impression that things are simpler.

For example, in microservices if you want some data that another service owns you have to define what it is, write an API, and handle all the fun of network problems. But once it's done you have a nice contract for getting that data.

In a monolith you can just reach over and take what you want. If you know there's a function for getting something you can use it. If you know the instantiated db connection has permission to view a row, just query the db directly. If you want to pipe some data somewhere just add it to the session object and it magically appears where you need it. And so on. You can go so fast! But then someone else does the same thing, and over time your monolith gets slower and slower, and needs more memory, and you find yourself having things on a god object that really shouldn't be there but it's hard to change because the behavior is threaded through everything.

Both of these problems are relatively simpler architectural issues, but it's always preferable to have well-defined complexity over accidental complexity. If you can define how code goes into a monolith and stick with those rules then a monolith is great. Most people can't, and I've never seen a company with multiple teams manage it.

You don't need network boundaries for good architecture. Split monolith into modules with an interface

That's a modular monolith, not microservices. It's a nice architecture for dev but it comes with a downside that you need to deploy everything whenever there's a change. You usually end up with a complex release train process. Again, the complexity is still there, but it moves. Where your complexity lives is a choice.

well... no, splitting a monolith once it has grown past the point where services make sense is incredibly difficult. My last employer spent a couple of years doing it and ultimately gave up. There is just way too much interdependency to split it up cleanly.

So the key here is good engineering leadership to recognize when that point arrives, and push the company to start the transition.

And indeed, microservices solve a organization problem not an engineering problem. When I taught the architecture to new hires, I always say: a service is the largest piece of system that stays together in a reorg :)

That's assuming you don't separate concerns in your monolith into modules with clear boundaries and dependencies. If you did that from day one, splitting a module off to a different service is easy.

If you can manage that then there's no real benefit to microservices though. The reason for splitting is to solve the problem of failing to separate concerns, so a team that can't do that well is better off building microservices from the start because the alternative for them is building a monolith that will be hard to split.

I don’t agree. The technical device we use for creating clear boundaries, useful abstractions and managing dependencies in monolithic code is the function/method/procedure call.

The history of distributed software is littered with the corpses of attempts to make the RPC look like a function/method call (I worked for a CORBA vendor decades ago). But these two techniques are so different on a fundamental level they are not substitutable except in the most trivial cases. The compute and elapsed time RPC overhead which makes perfectly good local abstractions completely impractical across a network. And then there are the differences in terms of failure modes, concurrency and synchronicity.

So even a beautifully designed and layered piece of “monolithic” software with a code base costing of coherent and clean abstractions will not be easy to port to a microservices/distributed architecture.

That's my belief as well: modular architecture and separation of concerns is orthogonal to monolith <-> microservice infrastructure axis.

And Service Oriented Architecture is the nice middle ground of that infrastructure axis

Big companies mostly seem to use the microservice(s) per team model. If your whole company is two founders, one account manager, and an engineer, you only have one team.

It can make sense to have more than one service for purely technical reasons. I once worked on a friend's startup where we built a separate ingress microservice so we could scale it independently from our monolith. There's no organisational benefit to doing so, however. The technical founder and the one engineer are hardly going to block each other.

"Big companies mostly seem to use the microservice(s) per team model. "

I am good with that. What we often see is 10 microservices per team of 3 devs. And ideally using the same database.

I've seen a startup with 10 devs + 60+ microservices and growing.

The team was stuck in a mindset that they just hadn't split things up enough to arrive at nirvana.

Been there before - I worked at a company where some geniuses thought that microservices would solve all of our scaling issues. We ended up with four microservices just to send an email (one to template, one to send, one to persist to database and one other which I can't remember now).

Multiple services using the same database will typically end poorly. When schemas or indexes change, how will that affect all of the different services? How do their read/write patterns differ? When one service needs to scale, will the additional connections starve the other services? And worse, if a service ends up moving to a different team or department, who controls the database?

I prefer a service that fronts the database. Swap the database, scale it, whatever, and clients keep going.

[dead]

Microservices are a solution to business/team organizational issues. Never technical ones.

I think the example I gave is a good counterpoint:

- you have a monolith, and it handles normal API traffic patterns

- you have a workload that involves different hardware needs e.g. extremely high throughput relative to the rest of the system (video streaming would be an example), GPUs, high memory requirements with low CPU or vice versa, etc.

Solution is to deploy a service that only handles the specific workload. Whether or not this is a microservice probably depends on your point of view but I'd argue it's at least close.

You can have microservices inside a monolith. It has the advantage of always deploying in a synced state.

Yes start with a monolith but split it sooner than later ( was at a company where they realized it too late, after being in business for 8+ years) .

It was a nightmare at that point. We pretty much gave up.

I worked at a startup where a new architect decided everything needed to be split into micro services for “scaling”.

Thing is we were in an illiquid market that didn’t require the kind of scale he envisioned.

Long story short we burnt a hell of a lot of runway building something that was painful to work with compared to the monolith. It did not end well.

Micro services are something that sounds good to the inexperienced but are almost never right for an immature business looking for market fit.

If you really know you can’t scale with just a big box from the outset use something like Elixir or Erlang. Otherwise stick to a modular monolith for as long as you can.