Navigating the Age-Old Software Architecture Dilemma With NATSby@andriivolotskov
451 reads
451 reads

Navigating the Age-Old Software Architecture Dilemma With NATS

by Andrii VolotskovAugust 9th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

In today's dynamic software development landscape, a recurring dilemma exists: whether to adopt a monolithic or microservice architecture. Here's my take on how the horizontally scalable monolith can revolutionize the architectural landscape. Dubbed the "Flex Architecture," this model endeavors to marry the best of both worlds.
featured image - Navigating the Age-Old Software Architecture Dilemma With NATS
Andrii Volotskov HackerNoon profile picture

In today's dynamic software development landscape, a recurring dilemma exists: whether to adopt a monolithic or microservice architecture. Both come with their unique strengths and challenges.

To start, let's clarify what these terms mean:

  • Monolithic Architecture: A single-tiered software application in which different components are combined into one program.

  • Microservices Architecture: A design approach in which an application is developed as a collection of loosely coupled, independently deployable services.

I was juggling many responsibilities dealing with both and would like to share some thoughts about it. While monolithic architectures are straightforward and more cost-effective initially, they can become complex and present scalability challenges as the system grows. In contrast, microservices promise impressive scalability but can be anywhere from 10 to 25 times more expensive for a company to set up and maintain — a cost that warrants justification.

Monolith vs Microservices cost dynamic for a single line of code

Monolithic systems start off cost-effective because everything is bundled together and doesn't require complex inter-component communications or multiple deployment setups. However, as the application grows, changes to any part of the system risk affecting the whole. Debugging, scalability, and deployment become more challenging, causing costs to rise sharply.

Microservices entail a higher upfront cost because each service is essentially its own application, requiring separate deployment, management, and communication processes. The initial setup is complex. But as the application grows, each microservice can scale independently, making the incremental costs more predictable and often more manageable than a monolithic system.

Transitioning Between Two Giants

Many have trodden the path of transitioning between these architectures, a process that's neither cheap nor simple:

Monolith to Microservices transition cost dynamic for a single line of code

  • In the beginning, teams develop the monolithic application, and the costs reflect typical development costs for a monolithic structure. These are relatively steady and manageable.
  • As the decision to transition to microservices is made, costs begin to rise. This is due to the complexities involved in breaking apart a monolithic application: understanding interdependencies, setting up individual microservices component-by-component, configuring communications between them, and ensuring data consistency and integrity.
  • As the transition progresses and more components are successfully migrated, the costs start to decline, reaching a new steady state as the system becomes fully microservices-based.

Despite the complexity of this approach, it is still very often the best way to navigate your architecture for growing, real-world organizations these days.

This brings us to a fascinating discussion I stumbled upon a podcast featuring Byron Ruth and David Gee. They shed light on the concept of horizontally scalable monolith. In this approach, each unit, app, or module is treated as an independent thread, co-routine, or process. Using NATS for internal communication, the design allows for the creation of multiple instances of each “unit” to handle the increasing user load. By leveraging NATS, this modular monolith method facilitates horizontal scaling with minimal latency.

This is a brilliant excuse for me to finally publish my vision about it. Also, I highly recommended that you watch the full podcast by yourself. Here's my take on how the horizontally scalable monolith can revolutionize the architectural landscape.

Introducing Flex Architecture

Dubbed the "Flex Architecture," this model endeavors to marry the best of both worlds. To better articulate its functionality and benefits, I synthesized my research into the following points:

  1. Foundation:
    • Apps (Units): Visualize these as distinct software pieces, reminiscent of “Django apps” for Python/"Spring modules” for Java/”engines” for Ruby on Rails but operating as separate processes. They communicate using Models data structures and are isolated from each other. The backbone? While there are many tools available, I personally favor Panini (built on the library) but bear in mind my involvement as a contributor.

    • Models: Serving as the communication data structure medium between apps. For instance, Python's dataclasses would be apt.

    • Streams: These are dedicated communication channels. NATS subjects are an ideal match. Here is my article about NATS if you want to know more.

  2. Repository Management:
    • Hosted in a single repository, it comprises:
      • Shared configurations, Docker files, and necessary packages.

      • Tools for running individual or all units, with Docker compatibility.

      • Integrated observability functionalities.

      • A unique feature allowing units to migrate to separate repositories, with "Models" as a submodule.

  3. Effortless Scaling:
    • Simple control of each “apps” instances number

    • As projects grow, Flex allows you to split them. The once-monolithic system now becomes multi-repository, with "Streams" and "Models" serving as either sub-repositories or packages. Each “app” is k8s-ready. Moreover, the architecture allows the integration of other languages, like Java, maintaining adaptability and efficiency.

The goal? To create an architecture that is based on the affordability of monoliths with the scalability of microservices. In case all functionality mentioned is build-in part of a framework, here is the economic impact I would expect for such architecture for the same growing organization:

Expected cost dynamic comparison Monolith to Microservices transition VS Flex architecture for a single line of code

Monolith to Microservices Transition: As discussed above, monolithic systems start cheap but become expensive to scale, while microservices have a high initial setup cost but scale more affordably.

Flex Architecture: Flex architecture endeavors to combine the best of both worlds. Initially, costs are low because the foundational setup resembles a monolithic system. You might notice, it begins slightly more expensive than the pure monolithic approach. This is because even though Flex Architecture uses a monolithic-like setup, it incorporates certain principles and structures (like isolated processes for each app or module) that may slightly increase the initial setup and development costs.

However, as the application scales and grows, the Flex Architecture shows its strength. Costs rise far more gradually compared to the transition approach. This is because the architecture is inherently designed for scalability without the need for a complete overhaul or transition. By allowing individual modules or apps to scale independently and communicate efficiently using tools like NATS, it avoids many of the pitfalls and expenses associated with transitioning from a monolith to microservices.

The results are self-explanatory. A significantly more economical and predictable cost structure emerges with this approach.


Imagine monolithic architecture as a reliable family car: cost-effective and simple but somewhat limited in speed and agility.

Contrast this with microservices, akin to a racecar: swift and versatile but resource-intensive and very complex to maintain.

Flex Architecture? Think of a nice hybrid car that fuses the family car's affordability with the racecar's prowess, offering a balanced, adaptable, and efficient solution.

While the Flex Architecture, as presented, is a theoretical construct derived from hands-on experience navigating between Monolith and Microservices, the convergence of these principles feels increasingly imminent. Given the trajectory of current software architectural trends, it's not hard to envision this hybrid model materializing in the near future.

Let me know what you think. Does it make any sense to your "monolithic vs microservices" problem case?