DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • Micro Frontends Architecture
  • Unveiling the Application Modernization Roadmap: A Swift and Secure Journey to the Cloud
  • Scaling Micro-Frontends With Orchestrators
  • MuleSoft: Do You Have an Extra Mule Under the Hood?

Trending

  • *You* Can Shape Trend Reports: Join DZone's Data Engineering Research
  • Docker Model Runner: Running AI Models Locally Made Simple
  • From Java 8 to Java 21: How the Evolution Changed My Developer Workflow
  • How Predictive Analytics Became a Key Enabler for the Future of QA
  1. DZone
  2. Data Engineering
  3. Data
  4. Before You Microservice Everything, Read This

Before You Microservice Everything, Read This

Microservices are powerful but often overused. Modular monoliths offer a simpler, scalable way to structure applications, especially at the start of a project.

By 
Nizam Abdul Khadar user avatar
Nizam Abdul Khadar
·
Jun. 16, 25 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
2.2K Views

Join the DZone community and get the full member experience.

Join For Free

The way we build software systems is always evolving, and right now, everyone's talking about microservices. They've become popular because of cloud computing, containerization, and tools like Kubernetes. Lots of new projects use this approach, and even older systems are trying to switch over. But this discussion is about something else: the modular monolith, especially in comparison to microservices.

But, why focus on this?

Because it seems like the tech world has jumped on the microservice bandwagon a little too quickly, without really thinking about what's driving that decision. There's a common idea that microservices are the perfect solution to all the problems people have with traditional, monolith application systems.

From my own experience working with systems that are deployed in multiple pieces, I know this isn't true. Every way of building software has its good and bad points, and microservices are no different. They solve some problems, sure, but they also create new ones.

First, we need to get rid of the idea that a monolith application can't be well-made. We also need to be clear about what we actually mean by "monolith application," because people use that term in different ways. This post will focus on explaining what a modular monolith is.

Modular Monolith – What Is It?

When we're talking about technical stuff and business needs, especially how a system is put together, it's really important to be precise. We need to all be on the same page. So, let's define exactly what I mean by a modular monolith.

First, what's a "monolith"? Think of it like a statue carved from a single block of stone. In software, the "statue" is the system, and the "stone" is the code that runs it. So, a monolith system is one piece of running code, without any separate parts.

Here are a couple of more technical explanations:

  1. Monolith System: A single-application software system is designed so that different jobs (like handling data coming in and out, processing information, dealing with errors, and showing things to the user) are all mixed together, instead of being in separate, distinct pieces.
  2. Modular Monolith Design: This is a traditional way of building software where the whole thing is self-contained, with all the parts connected and relying on each other. This is different from a modular approach, where the parts are more independent.

The phrases "mixed together" and "parts are connected and relying on each other" make single-application design sound messy and disorganized. But it doesn't have to be that way. To sum up, a monolith is just a system that's deployed as a single unit.

Let’s get into a deeper look.

To understand what "modular" means, let's define it. Something is modular if it's made up of separate pieces that fit together to make a whole, or if it's built from parts that can be combined to create something bigger.

In programming, modularity means designing and building something in separate sections. Modular programming is about dividing a program into separate, interchangeable modules, each responsible for a specific task. A module's "interface" shows what it provides and what it needs from other modules. Other modules can see the things defined in the interface, while the "implementation" is the actual code that makes those things happen.

For a modular design to be effective, each module should:

  1. Be independent and interchangeable.
  2. Contain everything they need to do their job.
  3. Have a clearly defined interface.

Let's look at these in more detail.

Independence and Interchangeability

Modules should be as independent as possible. They can't be completely separate, because they need to work with other modules. But they should depend on each other as little as possible. This is called Loose Coupling, Strong Cohesion.

For example, imagine this code:

C#
 
// Poorly designed module with tight coupling
public class OrderProcessor
{
    private readonly InventoryService _inventoryService;
    private readonly PaymentService _paymentService;

    public OrderProcessor(InventoryService inventoryService, PaymentService paymentService)
    {
        _inventoryService = inventoryService;
        _paymentService = paymentService;
    }

    public void ProcessOrder(Order order)
    {
        _inventoryService.CheckStock(order);
        _paymentService.ProcessPayment(order);
    }
}


Here, OrderProcessor is tightly linked to InventoryService and PaymentService. If either of those services changes, OrderProcessor has to change too. This makes it less independent.

A better way is to use interfaces to make the modules less dependent on each other:

C#
 
// Better design with loose coupling
public interface IInventoryService
{
    void CheckStock(Order order);
}

public interface IPaymentService
{
    void ProcessPayment(Order order);
}

public class OrderProcessor
{
    private readonly IInventoryService _inventoryService;
    private readonly IPaymentService _paymentService;

    public OrderProcessor(IInventoryService inventoryService, IPaymentService paymentService)
    {
        _inventoryService = inventoryService;
        _paymentService = paymentService;
    }

    public void ProcessOrder(Order order)
    {
        _inventoryService.CheckStock(order);
        _paymentService.ProcessPayment(order);
    }
}


Now, OrderProcessor depends on abstract definitions (IInventoryService and IPaymentService), which makes it more independent and easier to test or change.

Modules Must Contain Everything They Need

A module has to have everything it needs to do its job. In a modular monolith, a module is a business module designed to provide a complete set of features. This is called Vertical Slices, where each slice is a specific business function.

For example, in an online store, you might have modules like OrderManagement, InventoryManagement, and PaymentProcessing. Each module has all the logic and parts needed to do its specific job.

Modules Must Have a Defined Interface

A final key to modularity is having a well-defined interface. Without a clear contract, true modular design isn't possible. A contract is the "entry point" to the module, and it should:

  • Be clear and simple.
  • Only include what clients need to know.
  • Stay stable so it doesn't cause problems.
  • Keep all the other details hidden.

For example, you can define a module's contract using interfaces:

C#
 
public interface IOrderService
{
    void PlaceOrder(Order order);
    Order GetOrder(int orderId);
}

public class OrderService : IOrderService
{
    public void PlaceOrder(Order order)
    {
        // Implementation details
    }

    public Order GetOrder(int orderId)
    {
        // Implementation details
    }
}


Here, IOrderService is the contract, showing only the methods needed to work with the OrderService module.

Conclusion

Building a monolith system doesn't automatically mean it's badly designed, not modular, or low quality. A modular monolith is a single-application system built using modular principles. To make it highly modular, each module should:

  1. Be independent and interchangeable.
  2. Contain all the necessary parts to do its job (organized by business area).
  3. Have a well-defined interface or contract.

By following these principles, you can create a modular monolith that has the simplicity of a single application with the flexibility of a modular design. This is especially useful for systems where microservices might make things too complicated.

Modular design application microservice

Opinions expressed by DZone contributors are their own.

Related

  • Micro Frontends Architecture
  • Unveiling the Application Modernization Roadmap: A Swift and Secure Journey to the Cloud
  • Scaling Micro-Frontends With Orchestrators
  • MuleSoft: Do You Have an Extra Mule Under the Hood?

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: