Monoliths and Microservices

Iain McDonald — Engineering Manager

The journey not the destination

So often when thinking about the technology stack, company processes, or organisational structures within an internet economy company, we look to follow The Best Way; The Correct Way; The One and Only True Way Things Should Be Done. But the truth is that there’s no definitive answer for how a company should operate. Instead there are lots of “it depends” alternatives.

Internal Open Source, aka Innersource, is the idea that a company, within its own boundaries, should operate like a miniaturised version of the global Open Source movement. To illustrate why innersource is such a fundamentally important thing to get right, I’m going to begin talking about one of those “it depends” choices: building monolithic or microservice software architectures.

Monoliths bad, microservices good

Microservices gained popularity as a concept around ten years ago. Monolithic software architectures solve multiple complex problems in a small number of web services that may contain hundreds of classes, and connect to a single relational database. Individual microservices by contrast aim to solve one specific problem — by defining the boundaries of responsibility, microservices communicate with each other via well defined (RESTful) APIs. Neither approach is right or wrong, but rather they are appropriate for achieving good throughput with a different number of engineers. Too many engineers working on a monolithic design end up getting in each other’s way, and time between releases increase. Too few engineers working on a set of microservices spend too much of their time concerned with APIs and managing the operation of several different services.

In isolation, a microservice is simple and elegant. Often stateless, they solve a single aspect of a wider system. Unlike monoliths, their dependencies are smaller, their testing less troublesome, and edge cases fewer in number. However, there are more of them. The overhead of all the standard stuff is duplicated for every single microservice: containerisation, deployment, scaling, event monitoring and alerting, logging, security etc.

This is why startups and other small ventures still create software in the monolithic server + database design, and transition to microservices when the issue of scaling becomes too problematic. Amazon had thousands of employees developing software systems before Jeff Bezos announced the pivot to a service oriented architecture (another step on the journey) as described in Steve Yegge’s seminal internal Google memo. Looking at the popularity of serverless computing, we see that microservices aren’t even the last point on that journey.

Transition

Part of exponential growth is acknowledging and recognising that what worked for you yesterday, will hold you back tomorrow (to paraphrase Elizabeth Gilbert). At some point the monolithic architecture which enabled fast collaboration between a small number of engineers, will be an overall drag once too many new employees join, or a big new project kicks off. At this point, your company may begin to split up functionality into more separate processes aiming to arrive at a system of microservices. Given enough time, collaboration, leadership, and hard work, it’s possible to transition from this hypothetical monolith architecture:

Monolithic Software Architecture

to a system of microservices:

Microservices Software Architecture

Teams own business problems, not code

As much as engineers focus on the code they run, and the services they support, it’s all pointless without users. To succeed in business, you must be solving a problem for somebody: and it’s here where an unexpected artefact of separating code begins to show. It’s not always possible to perfectly separate software services and business problems.

Service Ownership Overlaps

Consider the situation where we now have six teams (represented by different coloured regions) owning different business problems, who in turn look after the most appropriate microservices and databases. For the existance of tradeoffs with no perfect answer, or perhaps simply historical reasons, incursions into multiple codebases are needed in order to fully own a business problem.

Why this is an issue

The team who cares about solving the business problem should be the ones to determine how important and urgent the work is to complete. When work crosses the divide of service ownership, the default tendency is to raise a request with the service owner and wait for them to complete it. However, they will complete it according to their priorities, which could be completely different to those of the requester. The business leadership may fund the most critical business problems with the appropriate number of engineers, but technical issues such as these introduce unexpected bottlenecks that render the planning redundant.

For example, consider a situation where Team A is funded with 10 engineers and Team B is funded with 2. The business considers the value of Team A to be five times more than that of Team B given the amount of budget it has. If Team A become blocked by requiring a change to the codebase owned by Team B, Team A need cooperation to deliver their goal. Team A’s request to Team B will be considered low priority because they have their own backlog to get through. By conflating business and engineering prioritisation, getting things done requires politics and favours. Thankfully, copying the open source model gives us a better way of working.

Innersource: internal open source

Rather than seeing service ownership as a divide that is locked down and cannot be crossed, engineering teams should see themselves as guides as to how their services work, and invite others to contribute freely. The reverse is naturally true which gives engineers the freedom to solve problems in any codebase within the company. This may require broad cultural changes, but it solves many technical issues.

Specifically, the transition to an increasing number of microservices introduces problems with: finding the correct codebase(s) to change; understanding the service specific challenges necessary to make changes safely; agreeing who supports the code in the future etc.

Resolving the above in a way which is simple and straightforward for both the team owning the service, and the team trying to solve the business problem, is not easy. This is the goal of innersource: to reduce friction, to make the overhead of solving business problems wherever they exist within the company’s software, as quick and pain free as possible.

Getting this right across your organisation will interact with all aspects of it: the tech stacks you choose, the internal processes, and organisational structures. This blog post is the first in a series about the challenges and victories we’ve faced in Skyscanner at building a collaborative, frictionless innersource culture.

Internal Open Source

This is part 1 in a series of 3 posts

SEE the world with us

At Skyscanner, we’re for travellers by travellers. Our employees can work up to 30 days a year from any of our 10 global offices on our SEE (Skyscanner Employee Experience) programme and even do up to 30 days home country working if you’re based in an office out of the country you call home. Of course, there are always chances to travel to the other offices for work trips or conferences too.

Like the sound of this? Look at our current Skyscanner Product Engineering job roles.

Join the team

About the author

My name is Iain McDonald, an Engineering Manager based in Edinburgh. I started programming by stumbling into BASIC on the Atari 800XL, and have been hooked ever since. I share random code and blog posts.