Last week, in What is the best Tech Stack for my Startup? Software Architecture Series, Part II we’ve explored the concept of using the most accessible technology stack at your team’s disposal. Achieving concrete, measurable results often trumps the endless seek for perceived engineering excellence.
Within modern engineering departments, you will often find people of different skills and backgrounds, working together. With the right kind of tools, you can empower your team members to develop, support and maintain resilient independent services, which are considerably easier to maintain than spiralling monoliths.
Where are monoliths adequate?
Before we can go ahead and call one technique superior to another, it’s important to understand where Monolithic environments excel and where problems start to arise.
In many young startups, even some mature organisations, you may find a single backend platform conveying every aspect of the business. This can be done in tools like Rails (Ruby), Symphony (PHP), Django (Python) and countless other examples.
Some companies might go as far as to create their very own monolithic system from scratch, often in an exercise of satisfying one’s perceived sense of technical superiority.
These monolithic platforms grow over the years, often what can be just a handful of core business features becomes a spiralling network of used and unused code, arranged in a somewhat inconsistent pattern born from a mishmash of requirements over years of development.
For very early-stage start-ups with a small team, even just the technical founder as the sole engineer, a monolith is easier to create and maintain. And it makes sense at the early stages of an unproved business to go with whatever is easiest to launch.
Once the business starts growing and the engineering departments become increasingly diverse, the monolith becomes a constant source of problems. What used to take days to develop tuns into weeks, simple changes inexplicably affect other parts of the project and the overall engineering output severely deteriorates.
What is a dedicated service?
Micro Services represent an alternative to the classical single-codebase approach, in which aspects of the business logic are split into independent modules which work together.
When designing a Micro Service, you must strike a balance between creating services compact enough to cover only one side of the business logic but also nimble enough to achieve their objectives without excessive fragmentation.
With over ten years of experience as a Software Architect, I’ve been an ardent promoter of the “less is more” ideology in software. Micro Services help achieve this by enabling smaller modules, which can be continuously refreshed without impacting other parts of the business.
Of course, things can also go the wrong way. In extreme cases, I’ve seen companies take the fragmentation problem to a whole different level. One particular customer comes to mind, where at the point that I’ve joined their organisation, I’ve found over 200 independent services.
This kind of fragmentation caused severe issues with orchestration, E2E testing, planning, maintenance and countless other daily tasks. What started as a genuine attempt to create a network of hyper-compact modules ended up as a web of trivial nodes all requiring extensive coordination to execute the business logic.
When you begin to architect a Micro Service, you need to define a clear set of specifications for your service, including:
- What part of the business logic will this serve?
- Which other services does it need to interface with?
- What is the dependency chart?
Micro Services can be developed in their own Tech Stack, best suited for the engineers developing them. This allows engineering leads the best optimise resources across a pool of developers and even allow for low-risk experimentation with newer technologies.
Should redevelop a monolith as a series of Micro Services?
With many fast-growing startups, this question arises as soon as the limitation of the monolith design become apparent. For almost every single instance, the answer would be no.
As engineers, we, unfortunately, have the tendency to underestimate the complexity of a given task. All “re-engineering” or “re-development” projects often get severely delayed because of a perceived sense of triviality in re-implementing an existing deployed platform.
A transition from a large monolith to a distributed network of services is a gradual process, where new features should be developed as new services and existing business logic is surgically extracted from the monolith to dedicated modules.
In the next few posts, we will go one by one on key aspects of The Polyglot Toolkit, including virtualisation, testing strategies, deployments and ideal design patterns.