Aligning Your Team around Microservices When There's No Precise Definition

This is a guest post by Roger Jin, Software Architect at ButterCMS and co-author of Microservices for Startups.

For a profession that stresses the importance of naming things well, we've done ourselves a disservice with microservices. The problem is that that there is nothing inherently "micro" about microservices. Some can be small, but size is relative and there's no standard of unit of measure across organizations. A "small" service at one company might be one million lines of code while far less at another.

Some argue that microservices aren’t a new thing at all and rather a rebranding of Service Oriented Architectures, while others advocate for viewing microservices as an implementation of SOA similar to how Scrum is an implementation of Agile.

How do you align your team when no precise definitions of microservices exist? The most important thing when talking about microservices on a team is to ensure that you are grounded in a common starting point.

But ambiguous definitions don’t help with this. It would be like trying to put Agile into practice without context for what you are trying to achieve, or an understanding of precise methodologies like Scrum.

Finding common ground

On one team I worked on, we tried to not get hung up on definitions and instead, we first focused on defining the benefits we were trying to achieve by adopting microservices:

Shipping software faster

Our main application was a large codebase with several small teams of developers trying to build features for different purposes. This meant that every change had to try to satisfy the different groups. For example, a database change that was only serving one group would have to be reviewed and accepted by others that didn’t have as much context. This was tedious and slowed us down.

Having different groups of developers sharing the same codebase also meant that the code continually grew more complex in undeliberate ways. As the codebase grew larger, no one on the team could own it and make sure all the parts were organized and fit together optimally. This also made deploying a scary ordeal. A one-line change to our application still required the whole thing to be deployed in order to push out the change. Because deploying our large application was high-risk, our QA process grew and we deployed less.

With a microservices architecture, we hoped to be able to divide our code up so different teams of developers could fully own them. This would enable teams to innovate much more quickly without tedious design, review, and deployment processes. We also hoped that by having smaller codebases worked on by fewer developers, our codebases would be easier to develop, test, and keep well organized.

Flexibly with technology choices

Our main large application was built with Ruby on Rails and a custom JavaScript framework with complex build processes.

Several parts of our application were hitting major performance issues that were difficult to fix and bringing down the rest of the application with it. We saw an opportunity to rewrite these parts of our application using a better approach, but inter-tangled our codebase was with the affected areas, this felt too big and costly to do.

At the same time, one of our front-end teams was wanting to pull away from our custom JavaScript framework and instead build product features with a newer framework like React. But mixing React into our existing application and complex front-end build process seemed expensive to configure.

As time went on, our teams grew frustrated with the feeling of being trapped in a big codebase that was too big and expensive to fix or replace.

By adopting microservices architecture, we hoped that keeping individual services smaller would mean that the cost to replace them with a better implementation would be much easier to manage. We also hoped to be able to pick the right tool for each job rather than having to go with a one-size-fits-all approach. We’d have the flexibility to use multiple technologies across our different applications as we saw fit. If a team wanted to use something other than Ruby for better performance, or switch from our custom JavaScript framework React, they could do so.

Microservices are not a free lunch

In addition to outlining the benefits we hoped to achieve, we also made sure we were being realistic about the costs and challenges associated with building and managing microservices.

Developing, hosting, and managing numerous services requires substantial overhead. A single monolith running on a few processes can easily translate to a couple dozen processes across a handful of services, requiring load balancers, messaging layers, and clustering for resiliency. Managing all this requires substantial skill and tooling

Furthermore, microservices involve distributed systems which introduce a whole host of concerns such as network latency, fault tolerance, transactions, unreliable networks, and asynchronicity.

Setting your own path

Once we defined the benefits and costs of microservices, we could talk about architecture without falling into counterproductive debates about who was doing microservices right or wrong. Instead of trying to find our way using others’ descriptions or examples of microservices, we instead focused on the core problems we were trying to solve.

  • How would having more services help us ship software faster in the next 6-12 mos?
  • Were there strong technical advantages to using a specific tool for a portion of our system?
  • Did we foresee wanting to replace one of the systems with a more appropriate one down the line?
  • How did we want to structure our teams around services as we hired more people?
  • Was the productivity gain from having more services worth the foreseeable costs?

In summary, here are the recommended steps for aligning your team that is jumping into microservices:

  1. Learn about microservices while agreeing that there is no “right” definition
  2. Discuss and memorialize your anticipated benefits and costs of adopting microservices
  3. Avoid too eagerly hopping on the microservices bandwagon–be open to creative ideas and spirited debate about how best to architect your systems.  Stay rooted in the  benefits and costs you have previously identified.

Focus on making sure the team has a concretely defined set of common goals to work off of. It’s more valuable to discuss and define what you’d like to achieve with microservices than it is to try and pin down what a microservice actually is.