We went from a large, monolithic backend application worked on by 100s of devs into docker based microservices, deployments using ansible and similar DevOps fluff. Here are some notes on the process:
- Determine the domain boundaries inside your monolithic app. Make sure calls between boundaries happen as less as possible (by call I mean either in-process calls, or database access).
- Split the devs into teams, and assign each of them one slice of the domain. (It is possible that one domain will be worked on multiple teams as well)
- Specify cross boundary calls still happen, and define an API around it. Make sure only this intermediate library is used when doing cross domain calls.
- Have proper tests around these intermediate libraries, that check that they are working properly.
- Split up the code based on these domain.
Now, each of your teams should be both smaller, and work on their piece of code without worrying too much about the others. The tests you put into these intermediate libraries should cover regressions from outside callers, and the internal code is your responsibilty. Obviously if the intermediate libraries needs changes, or if your tests tell you that you are not adhering to the API specifications anymore (which can, and will happen occasionally), then you need to start talking to the other team(s) using these APIs.
Once you are happy you can try to replace these intermediate libraries to be HTTP API calls instead of in-process calls. Once this is done, you can actually split up your large app into real, smaller pieces (they will probably still not be "micro" services, but much-much smaller and more manageable). Also they will at least belong to one specific domain, and also have a clear, well defined API that others (including new microservices mostly free of your legacy big app) can use to obtain their data.