Microservices: What and Why
Posted on May 30, 2016
We’ve spent the last year at Home Depot building a C# microservices platform with the new ASP.NET Core. This has been an exciting development and we’re really happy with what we’ve achieved so far. Over the coming months, we’ll be open-sourcing our framework and sharing our experience. I’m going to write a series of posts that cover all of the gory details, but first I’d like to start with the basics of what a microservice is and why they are interesting.
You’ve probably heard about microservices already. It’s the kind of new hotness buzzword that comes around periodically and is so overused that it could be about anything or nothing at all. It might be a silver bullet, or it might not be useful to you at all.
Let’s cut through some of the ambiguity and talk about what microservices are and why you might be interested in them.
You may hear other definitions, but at root a microservice is just a set of related web API endpoints. The “micro” part of microservice just means that a microservice isn’t a random grab-bag of APIs. Instead, the endpoints have very specific responsibilities that are all related in some way; the endpoints are a small, meaningfully grouped subset of a larger API surface. There is a lot of debate over how big a microservice should be, but that is mostly pedantic. The real question about organizing microservices isn’t about their size, but their domain of responsibility.
The way I think about microservices is by considering how a microservice-based API differs from the API surface of a traditional web app.
A monolithic web app might organize 100 different endpoints into route-based clusters (think /api/account/login, /api/account/changePassword, /api/product/search, /api/product/purchase, etc), but all of these endpoints are hosted on a single web server. To scale out, you run duplicate copies of the monolithic web app with its 100 endpoints on more web servers and load-balance them.
With a microservice design, we would segregate these API endpoints into free-standing web applications, each potentially running on a separate web server. We would pick which endpoints belong in which microservice based on the responsibility of each endpoint. Perhaps all of the /api/account endpoints would be included in the account microservice and the /api/product endpoints would be part of the product microservice. The end result of the microservice design is a number of small web applications, each providing some subset of the total API surface.
So now instead of a single web application hosting 100 endpoints, we have say 10 applications hosting 10 endpoints each. Why would we do this?
Scaling granularity. The workload of a web application API surface isn’t evenly distributed. For example, in a storefront application, account-related APIs such as password reset are probably used much less frequently than the APIs to search products. Why duplicate the account APIs on a dozen web servers just so that you can scale the product search APIs to a dozen servers? With microservices, you could run 2 instances of the account microservice and 12 instances of the product search microservice. With a sophisticated monitoring and deployment solution, you could dynamically scale just the parts of your API that experience load.
Deployment granularity. In a monolithic application, fixing a bug or releasing a new feature means redeploying the entire application. With a microservice implementation, only the microservice containing the affected code needs to be redeployed. Since any given microservice is smaller than the entire web application, deployments are faster.
Versioning granularity. A monolith deploys as a unit, so the application front-end must be updated simultaneously with any back-end API changes. This introduces risk. Microservices offer the potential for running multiple versions of an API concurrently, allowing the application front-end to be updated separately from the back-end.
The Why Not
The new hotness is always exciting, and it’s tempting to think that a microservice design will solve all of your problems. It won’t. In fact, there are many hazards and you should think twice before adopting microservices.
Complexity. You had one application before, and with microservices you’ll have ten applications. Or a hundred applications. A microservice implementation requires more supporting infrastructure than a stand-alone web application. There’s more that can (and will) go wrong.
Troubleshooting. When you see an error in a web application that uses microservices, it’s harder to understand where the failure occurred. The front-end and the back-end are hosted on different machines. If you have multiple instances of a microservice running, which instance responded to the request, and which machine is that instance running on? The log files are also distributed across multiple machines, so if multiple services are involved, you have to correlate the contents of multiple log files to see what happened.
Development experience. Standing up a copy of a monolithic application on your development machine can be a chore, but standing up a set of ten microservices to test your front-end against can be daunting.
If you’re still ready to take the plunge, there’s good news. It can be done successfully, and microservices can offer a whole new level of effectiveness in delivering and operating web applications. With the right tooling, developing microservices can be fun and even easier than working with a traditional web application.
In postings to follow, I’ll share our experiences building and running a microservice framework at Home Depot. Let’s do this!