Of course, on the other hand over-engineering at an early phase of a project is very much a thing too - starting with microservices, using the latest framework or language, etc.
Microservices however unfortunately have become a fashionable cure-all that's applied indiscriminately to software projects of all sizes, ages and purposes. Hardly anyone seems to be asking anymore why they're actually using microservices. Everyone uses them because everyone else does.
Microservices always incur overhead both in terms of engineering and network latency as well as maintenance / administration. If you have more than 1 microservice you need infrastructure for orchestrating and monitoring these services.
For all that to be worth it you need to have pretty solid arguments for using microservices in the first place. For a new project I'd usually advise against using microservices right from the start. Doing so is often rooted in the same kind of fallacy that has people worry about Facebook-scale scalability before they even have their first user.
If you start having problems that can be solved with microservices then good for you! This means your software is successful and has grown so much in terms of features and responsibilities it's starting to become intractable with standard approaches.
This is precisely why Martin Fowler argues for starting with a monolith first: https://martinfowler.com/bliki/MonolithFirst.html
A traditional monolith gives you the opportunity to learn about the problem domain first without having to worry about implementation details such as microservices.
Makes perfect sense to me.
A lot of what he's arguing against is cargo cult programming, and I think it's fair for anyone to argue against that. If your only explanation for why you chose one architecture or design pattern over the others (especially if that option introduces a lot of additional drawbacks) is "because that's just what you do", you need to stop and objectively evaluate what you're doing.
There is a link on that page for the more generic dataflow based programing. I'd advise anybody to follow it and simply ignore its specializations until they master the generic one. I'd also say that any program should be designed from multiple points of view, so do not stop at dataflow.
That's my yardstick - if I see poor man's distributed transaction attempts happening across service boundaries I'll start to assume over-engineering / cargo culting. If I see services acting a nodes in an pipeline or a flowchart, preferably with multiple incoming lines, it smells better to me.
If you are doing microservices, I hope you have a good reason for doing so. Because there are significant problems with using microservices.
In the last five years or so, I've done contract work at several large corporations. In every single one, they didn't care about defects or code structure. They just wanted to ship an application in a very short period of time.
When I asked about the same thing you pointed out, the response was the same, "We don't care about defects once it's released, and we don't care what the code looks like. It needs to work well for our end users, nothing else. Besides, in 6 months, we're going to redesign and rebuild it anyways."
It just seems nobody cares about long term maintenance, and likewise, they don't care much about the code or the amount of defects that code is generating. Pretty maddening when you think about it. Nobody cares about quality anymore.
1) working great and well for the end user, for the function of the software
2) bugs and code structure
Code quality can be so bad that it matters. But beyond a basic level, it does not matter. Bad code that works beats great code that doesn't fulfill it's function every single time.
I once had this great lesson. I was brought into a team as a TL/Manager. We were making a product that was doing pretty well, in terms of attention it was getting and so on. 1 week in, I learn that about 70% of the code is tests, 30% is actual code that's used at runtime. 2 weeks in I learn that everybody's always working on the tests, never on the program (there's a reasonably good reason for this even). 3 weeks in I explore the program, and at some point I try to run it. Turns out the "main" function is broken. Because of crashes (plural) during variable initialization it never gets to the first line of the main function ... How long had these bugs existed (it wasn't just one), you ask ? Well, over 3 months. Doesn't happen in the (VERY extensive) test run.
Lessons learned in that project:
1) test driven development is a great place to start, and a VERY bad way to run projects once they're even 10% into their delivery schedule
2) even the best tests don't check everything
3) even the best tests don't guarantee that even the most basic simple parts of the program work. In fact, tests actually WORK AGAINST THIS.
4) the value of a system test (where the entire program runs, by actually going into main and doing what it's supposed to on a realistic example) is incredible. The criticism that TDD developers have is valid, that if it fails you won't know (necessarily) where it failed, but isn't that serious. Firstly, you'll usually have some idea of where it failed, and secondly, and this is the big one, you'll know it fails. FAR preferable to the other situation. They're also very hard to write. Tough. You need them, far more than you need unit tests on 5 line functions.
5) you are MUCH better off with a "hero" programmer (bad name, "loose cannon" would be more apt description) AND someone acting 90% anal about tests, and managing the inevitable conflict, than you are without the loose cannon. Managing that conflict will be a challenge though. And yes, that means that, to the utter dismay of the TDD developer, you'll have to tell him to let in code without, or with bad tests, from time to time.
I've made the mistake at one company of thinking that my job was to architect solid software that was sustainable for the long term.
What they really wanted was to have software that was "good enough" and had all of the checkbox features to be attractive to potential acquirers so the investors would stop breathing down their necks.
Jack Dorsey became a billionaire from those losses. The same is true for probably all other early investors. For an investment in Twitter to have done really badly, there was a "bear" period of about 2 years.
And before you say it, remember that even Google stock dropped 60%, Facebook's 70%. Twitter's drop actually looks pretty reasonable in comparison.
So firstly, I don't think twitter is bad, and secondly, I don't think people have given up on twitter, and thirdly, that seems pretty justified.
Wouldn't you ?
As an employee who has a job because the company exists? Yes
As a retail investor - I wouldn't be quite as happy.
Contrast that to the small staff that Instagram had before getting acquired. It's still run on a relatively small staff now.
But in my experience, this is not true AT ALL. More experienced people might work less hours, but will produce the actual end results much quicker - both in hours and in calendar time.
Especially when considering that less experienced devs will (on the average) cause more bugs and worse code structure - in the long run this causes a ton of extra work. In my opinion that is the main difference that easily makes someone a "10x" or a "100x" developer.