Deconstructing “services”
I think when people talk about breaking things into “services”, it’s often a conflation of three different concepts:
- Hard interface boundaries (code organization)
- Independent code release cadences
- Isolation of compute resources
The first is typically what’s most important for keeping a large codebase maintainable; having clean interfaces helps make code easier to reason about and easier to change parts of. Services can be nice because it’s a lot harder to stick to a hard rule of “no, you really must not import my private method” if there’s a network boundary in the way — but if you are reasonably disciplined with a strong linting strategy then you can achieve this goal no matter how your code is deployed.
Having a single deploy cadence is often convenient in a monolith-ish codebase, but if you want to decouple the deploy timings, services aren’t the only answer: you can also make internal packages with strong interfaces and deploy more quickly or less quickly than changes to their callers’ code, even if they end up in a single binary.
Finally, separation of compute. I’ve even seen several cases where the same exact code is deployed to multiple services that receive different traffic patterns. This can be nice to avoid one noisy neighbor hogging resources from other work, to provide stronger failure isolation, for different hardware requirements, to be thoughtful about data locality (e.g., it can be helpful to colocate a cache with code that uses it), to have more control over server lifetimes, and probably more that I’m not thinking of right now. But this alone doesn’t solve the other two at all! And of course there are costs — sometimes large ones — to turning function calls into network calls.
I find it helpful to be specific about which (or which combination) of these goals is the desired result when discussing splitting things out, to be precise about what we’re solving for at any given time. The details often matter and it’s easier to talk about them if we’re specific about what benefit we’re trying to get.