I joined my current team a little over a year ago, and my first project was to add SSO support to our identity management service, and extract it into a standalone microservice that could be independently deployed
At the time we were working with a traditional web application; single repo, single build artifact, but internally divided into multiple modules that gave us a pretty good idea of where to start drawing our boundaries
We worked our way through that first service and established some patterns on how to split other services off and how to handle spinning up greenfield services
:D | D:
As you can see, we have a happy face, and a not happy face. I'm going to go through a few of the good things and not so good things we've run into throughout the process, and I promise it will sort of cleanly segue into Consumer Driven Contracts
faster deployments
With smaller services the time to actually deploy and start an individual service is shorter, but the real value is the ability to reduce the iteration time from idea to production
If you limit your changes to a single service, it becomes so much easier to safely and confidently deploy an update
Of course, this is something that's still possible to do within a traditional application, but the physical boundaries in a microservices architecture make it easier to do the right thing
automation required
Unfortunately, is that a certain level of automation is required to get those quicker deployments
Manual builds and deployments might work for you when you only have a single artifact to deploy once a quarter, but that becomes a lot less tractable as the number of services and frequency of deployments increases
You need to be able to automate your builds, and you need to have some level of automation in your deployments, and you should be able to quickly spin up all the required infrastructure to roll out a new service
fits in (human) memory
When you're working on a smaller, more focused service, it's a lot easier to maintain a full mental model of what the service actually does and how it works
Likewise, when you're acting as the consumer of a microservice that has a well defined interface, you don't need to worry as much about what it's doing internally
Treating it as a black box can do a lot to reduce your mental overhead
tracing requests
Tracing a request from end to end obviously becomes more difficult when you go from 1 process to more than one process
You now have to worry about crossing REST and messaging boundaries... you can't just figure out what's going wrong by tailing and grepping your logs
You need some sort of log aggregator, be it elk or splunk or something else and I would strongly recommend using something like zipkin to generate correlation ID's and insert them into your application logs
code ownership
When everyone is responsible, noone is responsible
If you're the champion of a service, or your team has ownership of a service, you're a lot more likely to keep it in good shape
And because you're well acquainted with this smaller code base, it's going to be a lot easier for you to effectively add features and maintain it
code duplication
sort of related to this, is that shared domain objects and common libraries can cause a lot of friction as you start to divide your monolith
This is mainly because you lose the guarantee that everything is using the same version of that shared code...
It can be really difficult to make sure that version 5 of your domain object is still backwards compatible with version 2, which is still in use by that one service which hasn't been updated in 6 months
testing :D
The most obvious positive gain from starting to divide a monolith comes when your monolith's test suite is starting to slow down
If you pull out a service whose tests take 10 minutes to run, that's 10 minutes you're stripping off of every monolith build, which is huge
You'll also probably find some ways to optimize that service's build time once it's been split out due to ownership as mentioned earlier
Those clearer boundaries, smaller code base, and increased familiarity can also aid in testing your services in isolation
testing D:
The downside of course, is that you're no longer testing a single process
You need to make sure that each individual service works as intended, and you also need to make sure that they can coordinate together at a higher level and behave correctly as a system
Compounding on top of that, you might have different devs working on different services concurrently, so the versions you're testing your service against might not be the version they're getting deployed with