Scaling a Code Base
2023-02-07
The most important thing to optimize for when determining how to organize your codebase should be developer velocity. Most companies start out with a single, monolithic application in a single version control repository. You can and should try to stay this way as long as possible. In this world, problems only need to be solved once. Need to change your build system? You only need to do that in one place. That strange external dependency your codebase has to interact with? You only have to figure out how to interact with it once. Your developer velocity is faster overall because you never spend time solving the same problem twice.
As you scale, the monolithic application itself might no longer make sense. Again, I want to stress that your default instinct should be to keep things in the monolith. But there may come a time when you need to pull something out.
One reason could be for performance. Most webapps for example are going to be written in some high-level language like PHP, Python, Ruby, Node.js, etc. There may be a particular part of your app that is performance sensitive and it therefore makes sense to pull out into a more performant language. A good example of this is Facebook's newsfeed. Facebook found that the quicker they could render news feed, the more money they could make. So newsfeed was pulled out into it's own, non-PHP service.
Another good reason to pull out code from your monolith is if it needs to be used across multiple services. A good example of this might be an in house experimentation framework. This is something broadly useful across several services, so it makes sense to implement it once as it's own service.
There may be other reasons to pull out code into a separate service. In general, be judicious and you'll be fine. And remember, even as you're pulling things out of your monolithic application, you can and should still keep everything in one source code repository. All glory to the Monorepo.
If any of this isn't tracking for you, I highly recommend reading Let A 1,000 Flowers Bloom, Then Rip 999 of Them Out by the Roots. Seibel gives some great, real-world examples of the above.
A Note on Microservices
I've yet to find a good reason to make a Microservice. The costs of deploying a separate service are quite high. You all of a sudden need to figure out RPC, Tracing, a slew of AuthN/AuthZ problems, etc. So if you're going to deploy a new service, make sure it's actually meaty and the ROI is there. It's hard to see any Microservice meeting this criteria.