Microservices are a great way to build applications at scale (or at least preparing for scale). There a multitude of reasons why this approach is smart but I’ve also seen it overly abused. At a previous employer, we had a grand vision for a microservice based architecture. We planned it all out on the whiteboard and made all these different microservices by splitting things up into responsibilities. We ended up with a microservice for session, users, forms, application, 3rd party services, and I’m sure a few more that at the time we thought were Elon Musk level ideas. Whiteboarding ideas is great and all but it’s easy to over-optimize or complicate things.
As we started to build these individual microservice APIs, the team started running into some of the cons that microservices can introduce. By having to run multiple applications in order to replicate a live environment, you have to setup just the right state data (typically fixture data in the database) to get a successful output from all your services. If one service didn’t have the data setup just right, something would get messed up in another service or whatever and you end up not being able to run the application correctly.
Tracking it all down in a complex app becames a fun game…
Me and a dev on my team trying to figure out why the app on his machine isn’t working.
It’s easy to think that your Jeff Bezos when your building apps this way because after all that is what Bezos mandated. Just remember he told teams to expose APIs, not individual applications as islands of data for the heck of it. Just because you can build an application in an extremely complicated, multi-tier, self-healing, load balancaed, auto scaling, wiz-bang 9000 way, doesn’t mean you should. Another challenge we ran into was how much back and forth requests there were to do any single task. One microservice would have to call another to get another piece of data needed to hit another microservice. Some people think this is perfect for some environments and yea maybe if we were Netflix level we would have needed all that out the gate. I’d suggest you build your application with maintainace in mind, tests, and planning for the future. Just don’t build all the future stuff right now. Get the MVP done and released, then go back and refactor the parts that don’t scale or are starting to break down due to bottlenecks.
What we ended up doing is pivoting half way through the project and started consolidating multiple microservices into one monolithic service, or as we called it, a “macroservice”. There is a fine line with this architectural design pattern and it can be abused. Try and think of things in a more “object graph” fashion when building your services. If you have an object that needs to be built from 4 separate 3rd party APIs, with 16 queries across 3 databases, and at a certain point you can make the object dependency graph in your head or whiteboard it to understand what logic the service should be preforming. In that example, you may want to just include all those services into one macroservice. The idea is, if you ever start getting a ton of traffic, you can break out the services into separate microservices later or break out the database and scale those individually.
Monitoring, alerting, deploying, and just a whole bunch of tasks become a lot easier with our backend separated from your frontend. At my new company VehicleHistory.com we started implementing this type of architecture and are very pleased with the results so far. You can do cleaver things like have front end developers just pull down the main site which is pretty much a thin client to the backend microservices walled off from the internet and securely load-balanced on a private ALB (Application load balancer, thanks AWS).