"Just the right size"
“Just the right size”: Software architecture solutions to meet the needs of the insurance sector
It’s always been interesting to see how certain buzzwords propagate through the tech scene and into corporate boardrooms, shaping projects and decision-making in the process. For example, there’s “artificial intelligence”, “blockchain” and “cloud”, just to name a few. They’re all very important, but none of them is the universal solution for every problem in the IT world. Two of the hot topics on everyone’s lips today are “monolithic architecture” and “microservices”. But are IT solutions really that black and white? Is one alternative always good and the other automatically bad? Or does the truth lie somewhere in between, and is this even the right way to frame the question?
What is a “monolith”?
In the context of software architecture, a monolith is a single application that handles all necessary business processes. In the case of web applications, this could mean that access from the web, database operations, business logic, and output to an HTML page are all handled within the same application. This is a very widespread design pattern whose origins actually go back to the beginnings of the World Wide Web. For example, it’s used in many content management systems, guestbooks and forums, and has seen widespread usage in many other applications into the 2010s. So why is it suddenly “bad” – and what’s supposed to be the “better” way?
What are “microservices”?
In contrast to monolithic architecture, service architectures are characterized by the splitting of business processes into independent systems. A “service-oriented architecture” (SOA) is when the various application processes are split up into individual encapsulated services. Here, it’s not absolutely necessary for each of these services to be solely dedicated to one strictly defined task. But when applications are actually split up into these small elementary services, then we’re talking about “microservices”. This architectural model uses multiple services that can likewise be used separately, but these services are considerably smaller.
Here’s an overview of the three different architecture types:
Advantages of a monolith
Imagine that you’re working on a complicated spreadsheet within a non-monolithic environment. Having created the table, you’d now like to insert the result of a formula calculation. To do so, you first need to open another program called “Spreadsheet Functions” (i.e. a service) and then make the two programs talk to each other. Back in your spreadsheet, now you insert a command that sends the relevant attributes of your formula to the “Spreadsheet Functions” program. After a couple of milliseconds, you receive an answer with the result from the calculation. And now in the next step, you’d like to create a graph from your table – let’s say it’s a pie chart. To do so, you first need to open the “Spreadsheet Graphs” program, make the two programs talk to each other, and then send the necessary data to Spreadsheet Graphs before receiving the finished graph a couple of milliseconds later (or maybe longer, since the graph is so big).
You certainly don’t want to work like this. You actually want to open your spreadsheet program and complete all these jobs within the same program – you want a monolith.
In software development, we’re often faced with situations like the one in this (admittedly rather exaggerated) scenario. Splitting up all the functionality into a service architecture is not always the right choice. A monolith offers many advantages – not only for maintenance and deployment but also for debugging, since these can all be done within a single structure. The organization of the source code is also simpler when it’s all saved within a single code repository. Finally, it also makes monitoring much easier, with just a few centrally stored metrics to be checked. Beyond all that, with many applications, there’s simply no need or reason to split them up into services.
Reasons for a service architecture
Of course, the right software architecture very much depends on what kind of application we want to develop and what business needs the application has to satisfy. The example above is better applicable to a relatively simple application. For a more complex application, such as one that needs to be integrated with other applications into the same platform, it makes sense to split it up into logical or functional modules.
For example, suppose we’re operating a car insurance platform that’s faced with a steady barrage of up to 1,500 price queries per second. Through performance testing, we’ve determined that the technology chosen for our application can’t keep up with this traffic. Unfortunately, its monolithic architecture means we can’t simply replace this particular subsystem with a different technology. In such a case, the best strategy would be to implement a pricing service – one to be used not only by our affiliated aggregators but also by our own primary application. What’s more, this service could even be based on a different technology or programming language, potentially bringing further benefits. And just like that we’ve designed, created and deployed our first service.
This type of service can now be adapted for other parts of the application. We might have services for reporting claims, creating documents, calculating commissions or filling in a subledger, to name just a few examples. This architecture offers us greater flexibility in scaling the different parts of our application – or, more accurately, our platform. It’s also advantageous for future developments, because the pricing engine is now an independent software application. New versions can be designed, developed, tested, scaled and deployed separately from the primary application.
What’s the story with microservices?
By continuing development according to this model, we create a microservice architecture. At some point there may no longer even be a primary application anymore. All functionality has been outsourced to small autonomous services, each one specializing in performing one specific task. In most cases, the various services communicate with each other – either synchronously or asynchronously – through some type of messaging mechanism.
The advantages of a microservice architecture derive from the completely separate implementation of each solution. Often, microservices have just a few hundred lines of source code, making them not only easy to review and modify but also very fast to deploy. Another huge advantage is being able to scale each microservice individually. The scaling required for each microservice is determined by how many queries it receives and how often it’s called. The diagram below shows this in a greatly simplified way:
However, the complexity of the interaction between services should not be underestimated. It’s already a very complex task to keep track of the data points and values that each microservice holds at any particular moment, requiring very specific mechanisms along with the corresponding monitoring tools.
What’s the “right” solution?
There is no one-size-fits-all solution; it should always be a just-the-right-size solution. But what exactly does that mean?
For one thing, you can’t make every solution fit every requirement. Each of the solutions mentioned here has both advantages and disadvantages.
At sum.cumo, we make use of all three architectural models – and for good reason. An application for which we expect little traffic generally doesn’t need to be split up into a complex microservice architecture. The more involved development process and higher administrative overhead aren’t cost-efficient, and the deployment cycles are generally not very frequent in these cases. So there’s no call for a microservice architecture here – the focus is more on stability and ease of maintenance.
On the other hand, if a platform handles lots of traffic and many different transactions, then we need flexible scaling, fast deployment and rapid updating capabilities. For example, if you want to quickly serve many clients on the same platform at once, then it helps to be able to execute the same service multiple times. In this case, the benefits of a microservice architecture are clear.
Recent experience has shown that in most cases, moving toward a service-oriented architecture is the best strategy for insurance platforms. It’s important to note here that there’s no need to encapsulate everything in services right away. Organizing the source code into self-contained modules in the first place is a good first step that opens up the possibility for any one of them to be extracted and outsourced to a service – which may be either an internal service or a microservice – later. Even a hybrid solution is possible, though it requires careful consideration. Regardless of what architecture you choose, it’s critical that the source code be divided into clearly differentiated modules; otherwise you’ll end up with a blob of code that’s difficult to maintain – or even worse, with chaotically interwoven lines of unintelligible “spaghetti code”.
A good solution ought to be iterative, well written, clearly structured, developed according to need and accommodating of future maintenance and improvement. The way forward depends on the requirements of the particular business model.
There is no one-size-fits-all solution. Monoliths have certain advantages over microservices, and likewise microservices over monoliths. The project doesn’t begin with the choice of software architecture but with a detailed analysis of the client’s business model along with the implications that this has for IT requirements in the future. So good decision-making doesn’t simply follow the latest trends of the pundits – it’s built on careful consideration of all the necessary requirements.