I ended up restricting database access, but wouldn't have thought that was necessary. To me it was obvious all services should only communicate via their public API, but I guess that's not so much of a no-brainer as I thought.
I had to make an authorization service and the idea to use a single authorizer to handle token generation and authorization was shot down by management due to worry about "lambda startup times". I complained that the startup time is less than a second (for nodejs) and honestly would not be an issue. They gave the task to someone else to have the token generated in their service. The developer did it by copying the code I'd written into their own service verbatim.
This is why I don't like microservices as we do them. Management would rather we wrote small programs with a lot of duplicated functionality in many repos instead of writing a large program where we can enforce some discipline. This is also better for them because they meet with us individually to ask for functionality rather than have design or architecture meetings where we can push back on implementation details.
I'm very happy with this approach.
> Splitting up your application in many services requires a lot of thinking and designing.
In my experience, you spend a bit of time asking "What does my project do, and how do I decompose it?" and that's about it. The same thing you'd do with a single binary that you decompose into modules.
> Challenges with syncing, communication etc are not always easy to deal with.
Depends on what you're doing certainly. For me, I'm basically doing an ETL and analytics pipeline, so I have no issues there.
I have found it much easier to reason about code and boundaries. I did a ton of experimentation with code and services (I didn't know how to build it when I started, so there was tons of iterationt) and the ability to just rewrite any service fairly trivially helped a ton.
I haven't had to do any "splitting". Merging services is trivial, splitting is not. I'd much rather say "Ah, the synchronization here is too hard, I'll shove it into one process" than "How the hell am I going to scale these two modules separately with all of this shared memory between them?".
I've gone through a "We have to start splitting things for reliability/performance/conway's law" and it's years of very difficult, dangerous work.
It's really a "to each their own" but I don't think I overengineered things at all. Microservices just make sense for my use case.