In this series (part 1 / part 2), I have been writing about the merits of best-of-breed, as the middle ground between monoliths and microservices. So far, the subject has been limited to just the scale of the software – how many functions should one unit handle. There is another facet to this, however: which functions should be collected together into one solution.
This problem is
referred to as the separation of concerns. Or, more accurately, you should
consider the separation of concerns when you face the problem of dividing up
all of your requirements into units of software.
If you are not
familiar with the term, separation of concerns is the process of extracting
functionality relating to different domains into isolated units – as a
programmer that could be different modules, functions or classes; as an
architect that would be different components of the whole system.
To illustrate this
concept and explore why you might want to separate concerns, let’s go through
an example. Consider a website that requires you to log in to access its
content. This system has at least two concerns: managing content and managing
users. Now, if this website has a single database to store all data then it has
potentially mixed concerns. How could this manifest as a problem? Well, what if
the Asian and European markets are both very important for this site and
performance is critical? In that case, the GDPR mandates that the users are
stored within the EU but the latency of database calls from Asia to the EU
could be a problem. The crux of the issue is that there are conflicting
requirements upon the database. One concern (user management) requires that the
data is never stored outside of the EU and another concern (content management)
requires that the data is replicated between Europe and Asia. Obviously this is
an over-simplification but hopefully it illustrates the point.
In that example, the
resolution to the conflict is straightforward: use two databases – one for
users and one for content. That change exemplifies a separation of concerns in
a very literal way. Of course, that could cascade into the application tier or the
architecture. For the latter, that would mean having one standalone solution
for content management and a separate piece of software for user management.
So, given you have
taken the decision to use best-of-breed solutions – not monoliths – the
question of where to draw the boundaries between these solutions is
forthcoming. To answer that question you need to contrast two factors:
the benefits of proximity, control and intimate knowledge; vs
the risk of conflicts arising between two functions in the same black-box
To illustrate the
benefits of proximity, consider Identity and Access Management (IAM). These two
families of functions are very commonly bundled together because the decision
about access is intrinsically based upon the subject’s identity (“you can access this but they can not”). An access management tool
can exist independently with an integration to an external identity store but
then the management may be more convoluted, latency will slow the system down
and, if the integration fails, the whole system will cease to function.
From an architect’s
standpoint, the task is not just to cluster functionality into concerns but
also focused on identifying functions that should not
live together, because of the risks that coupling them expose your organization
to. Unfortunately, analysing the risk of a conflict arising is akin to
predicting the future. There are a few indicators you can consider, however…
Is the function (not system) mission critical? Is the function heavily
regulated, therefor subject to unpredicted change? Is the function
intrinsically linked to external systems? Is the function intrinsically linked
to client-side technologies, browsers, devices? Essentially, will one function
need to moved and/or be changed (with some degree of urgency) independently to
the rest of the system?
Finally, the vendors
you are assessing will clearly have opinions about the correct separations of
concerns and should be able to articulate them clearly.
For a true
best-of-breed system the same vendors will regularly work with each other in a
mutually beneficial and dependent ecosystem. The hallmark of best-of-breed is
that the solution sells by word of mouth. That network effect will naturally
cause the best software and, crucially, the most sensible integrations to
bubble to the top: “We really liked X and it worked great with Y but, to
be honest, the integration with Z was a mistake”.
Really, that final
point – the Darwinian emergence of a best-of-breed ecosystem – is the crux of
this series. It may be a challenging and multifaceted problem to architect a
complex solution but a combination of foresight and market-wisdom can be used
to mitigate the risks you take on.
In conclusion, the
size and situation of your business affect whether you should be using smaller
or larger solutions; monoliths are almost never beneficial; and, finally,
careful planning – not just for the architectural patterns but also of where
the split lies between various concerns in the system – will help you identify
best-of-breed solutions that are a good match to your needs.
In the previous post, I talked about the extremes of a spectrum of enterprise software architectures: from large monoliths down to microservices. tl;dr Monoliths are potentially simple solutions but inflexible; micro-services are very agile but come with architectural complexity. At the end of the post, I touched upon the question of whether simplicity and flexibility were of equal value and, hence, if the trade-off was linear.
It seems fairly
likely that this model is not correct – there will be some Goldilocks zone in
the spectrum, where the flexibility is enough and the complexity manageable. Of
course, that sweet-spot will not be universal: the size of the internal
technology team, how specialized the outcome is, the market and a host of other
factors will come into play.
In this post I am
going to explore a framework for modelling the payoff and take some best
guesses at how that applies to some example scenarios.
generalized framework for modelling payoffs
The examples that I
will explore in this post are imaginary; they are designed to illustrate that
there is not a one-size-fits all solution, nor a paint-by-numbers exercise to
find the solution for you. That said, there are aspects that I think are generally
applicable and that should be considered:
What is your objective and how are you measuring it? OKRs can work well for this.
What are the attributes of a project that will influence the objective(s)?
For the decision you are trying to make, how do those attributes play our between the extreme cases?
While you should
know point one and be able to intuit point two, the final one is tricky and
requires work. To effectively describe the landscape, you are likely to need to
produce a model in a spreadsheet and put some numbers in. You can guess the
numbers to start but it’s worth finding contacts in similar organizations who
are friendly enough to share their experiences and help you refine your model.
In the following
examples, keep the 3 points above in mind and consider them in the context of
startup – limited resources, both in time and budget
In this case, the biggest constraint may be budget. Where you do have budget to spend, you need to avoid one choice closing off other low cost options elsewhere in the stack. The trick will be to find an inter-operable set of software where no single pieces blows the budget. You probably won’t want to pay for engineers where you don’t get differentiating value, either, so the integrations need to be simple or out-of-the-box.
Build a functional system within budget
Project total cost of ownership less than X
Licence cost and team size
Here you can see the need to avoid expensive solutions – which will often rule out large enterprise suites – and, equally, you will not want the overhead of a committed team. If you can, buy best-of-breed where it differentiates you and open source or consumer-grade where it doesn’t. You will also want to plan your team size very carefully; while the steps in the illustration above are purely figurative, as a small company the impact of each FTE will significant.
funded new venture – trying to scale rapidly
If you have taken
investment to scale faster than the competition, the cost of delay far
outweighs financial outlay (at least within reason). You’ll need to get the
commodity stuff out the way quickly then focus on your differentiator. Bear in
mind – you might need to adjust course or even pivot, so don’t get locked in!
Get out an MVP and gather usage data
Key result 1
Project delivered in less than X days
Test-learn-iterate to achieve product-market fit
Key result 2
Deliver second iteration in less than Y days
Initial delivery time and time to change some functionality
Some kind of SOA
will allow you to adapt to changes as you try and achieve PMF: the big hump in
the left of the “Time to pivot” wave indicates the risk of getting a
single, inflexible solution for everything. The finance, in this case, is opening
up the width of the Goldilocks zone: with enough budget and motivation, you
could go all the way to true microservices.
company – fighting to get off a crippling legacy stack
overhead of a move away from a legacy stack can be paralysing. It’s a tough
pill but you’re going to have to swallow it.
The OKR is much
harder to define in this situation. It could be any one of many, For the
purpose of illustration I will chose one possible OKR:
Accurately track customer data throughout the enterprise
Reconcile Web Analytics with Single Customer View with an error rate of less than 0.01%
SCV de-duping accuracy, data integration reliability
architectural strategy will be integral to success and without it the project
risks spiralling into chaos. Plan your architecture wisely – hire an FTE to own
it, if you don’t have someone already. Something well structured like an
event-bus pattern is a good place to start, followed by a multi-stage migration
plan that minimizes risk.
There are going to
be a lot of requirements in a project like this as, if nothing else, it’s
difficult to get agreement to drop BAU functionality in a large organization.
That means a single monolith doesn’t exist. You might consider a suite, for
some areas of the business, but make sure the vendor is a safe pair of hands.
Failure here is
needing to do a large re-arch again. What you build now should last for at
least 3 years and the architecture should be designed to live a lot longer than
As called out in part 1, the monoliths are spread too thinly to realistically achieve a best-of-breed status for any of the functions you need but, at the other end of the spectrum, if you self-build everything you will never catch up with the attention-to-detail and resilience that a vendor will have finessed over years and multiple clients.
The bump on the
right hand side of the “Integration reliability” curve is for true
microservices, and is debateable. I believe that there are enough engineers out
there who are enthusiastic about micro-services that the right team will be
likely to produce a more reliable network of services because they will spend a
lot of time thinking about them.
Microservices inherently make you consider integrations, whereas that is less
of an emphasis if you have non-mission-critical integrations between a small
number of self-contained solutions.
To conclude the
second post in this series, I want to reiterate the sentiment that there is no right size of software. Small services work
well for some companies, large monoliths have their place too. The prevailing
With a little analysis you can identify which style of software will minimize the risk for you, as a buyer
The specialists near the middle of the spectrum will have the best quality solutions, as long as their market is large enough and healthy enough to support their growth – these are the best-of-breed solutions
If you have taken the decision to look to the middle of the spectrum – avoiding both atomic microservices and all-encompassing monoliths – the next question is how do you decide which functions live together. In the final post in this series I will focus on that question and explore how a separation of concerns can help keep systems operating effectively over time.
buyers have a really hard job. Aside from the specifics of meeting
requirements, there’s no escaping the difficulty of the underlying
architectural decisions an organization needs to make in order to buy well.
If the technology
systems of your company are simple – with few users and minimal integration –
you may be able to buy something that just does
the job. But, most often, that’s not a strategy that can scale with your
business or the changing technology landscape. Usually, there needs to be some
consideration of architecture even before shortlisting a vendor.
regularly comes down to buying a monolithic-solution or a point-solution. That
is, you can buy a monolith (or suite) that handles the majority of the
functional requirements of your business in one solution; or you can buy many
solutions that each fulfil one function. Of course there are some solutions
that fall between the two, which will be the subject of the next post in this
Now, on the face of
it, a solution that meets all of your needs in one tool is the obvious winner,
versus one that only meets a single need, but – as we all know – it’s not that
Personally, in order
to bring clarity to a difficult decision, I like to consider the polar
extremes: a solution that literally does everything ones business needs verses
a microservice that only handles the slimmest, most atomic function.
Take the example of
an online newspaper (as an industry I know well). They need solutions to, at
Publish content to the web
Manage registered user data
Hide content behind a paywall
Manage recurring subscriptions
Manage email lists
(In fact, the list
is much, much longer than that but they would definitely need to do those
consider the monolith. For a green-field publisher this might be an attractive
option. One vendor (throat), one set of training for their users, one bill.
And, hopefully, the whole business is supported by one integrated solution.
There are three
particular drawbacks to the monolithic approach.
One is that the
implementation project is likely to be huge, which constitutes a substantial
gamble: if the project goes wrong the cost could be existentially damaging,
particularly for a new business.
The second problem
is vendor lock-in. Assuming the project is a success, what happens a year or
two down the line if the publisher wants to change the way they send emails?
Maybe they were getting a lot of bounces; maybe the reporting is inaccurate;
whatever the reason, the solution is not cutting it and a better one is now
desirable. The issue at this point is that the publisher is paying for the
email sending functionality of the monolith, whether they are using it or not.
Finally, there is a more insipid problem of the development and maintenance. You should be cognisant to the fact that the vendor of a monolith is competing with several best-of-breed and point solutions, across different functions. If they offer a CMS (authoring & publishing content), an IDM (user data and auth’) and a paywall (access control & subscriptions) then there would be an alternative architecture with 3 separate best-of-breed vendors or 6 point solutions; so the monolith’s development team (and other teams) would need to be in the same order as 3 best-of-breed vendors combined. If they’re not, how can they be investing in their product competitively?
So, what about
The benefits of
microservices are well documented elsewhere
but, to summarize, because each service is modular and focused they can be
built and maintained more easily and quickly. The service only has to worry
about one thing and has a strict interface between it and other services so:
you can rebuild or refactor them often, without worrying about the rest of your stack;
you can use different technologies and programming languages for each service, picking the most appropriate for each, and;
when you release, you are testing an isolated scope.
All of that is
predicated upon the architecture being responsible for the interactions between
the services. A development team can safely work on just, say, Content
Authoring because there is a strict
interface (what comes in and out of the service must not change) and there is
some kind of transport between them, such as an event bus or HTTP calls.
The real challenge
with microservices is that architecture – the glue between the services. Each
service is less complicated but the entire system is a whole lot more complex.
Some services might be built in house, some bought; in that case you need to abstract
the APIs of the bought systems to fit in with your interfaces, which means an
API gateway, of some kind. The services you build yourself need to be
containerized, load-balanced and auto-scaled. You need to monitor performance
at either the interface or the network level to identify bottlenecks… It gets
In some cases,
another down-side to a microservices architecture is performance. This one is
arguable and depends a lot on specifics but more network request between the
interconnected web of services means more latency. That should be considered
So, from this point
of view we can see there is a trade-off between simplicity and flexibility.
Monoliths are simple solutions, in many senses, but really undermine
organizational flexibility; Microservices are flexible but come with an
architectural complexity that should not be underestimated.
If these two traits
– simplicity and flexibility – are equally valued and dissipate linearly from
one extreme to the other then there is no outright advantage for any particular
point on the spectrum. You would just chose the solution you liked. That, however,
is probably not the case.
The value of each
trait is absolutely dependent upon your team and existing systems. If you don’t
employ any solutions architects then the value of simplicity is massively
inflated. If you have very unique requirements that can only be built bespoke,
then flexibility may be more important for you. In part two of this series I
will have a look at some example cases and explore a framework for answering
the question “how big should your software be”.
In practice, most
enterprises will have some blend of solutions from across this spectrum.
Extremes are generally risky and solutions that fall somewhere between
microservices and monoliths may be the pragmatic choice. In part three of this
series I am going to explore which functions should be collected into
best-of-breed solutions and why.