Modular Deployment by Profiles: How to Scale Your Architecture Without Microservices Chaos

Published by
Luis Benavides
 Modular Deployment by Profiles: How to Scale Your Architecture Without Microservices Chaos
Written by
Luis Benavides
Published in
May 12, 2026
Reading time
4 min
Category

Have you ever felt that your project is too large for a monolith, but too small for the operational complexity of microservices? Perhaps you’ve been forced to split your code into multiple repositories just to scale a specific part of the system.

In modern software development, there is a strategic middle ground: Profile-Driven Modular Architecture. This approach allows the deployment topology to be a simple runtime configuration decision, eliminating unnecessary technical friction.

To demonstrate this, we will explore ModularMS, a project that exemplifies how this model allows you to transition between different architectures without rewriting a single line of business logic.

The Technical Dilemma: Monolith vs. Microservices

Normally, the scalability path is rigid: you start with a monolith and "evolve" into microservices through a massive rewrite. However, this step often brings the "distributed complexity tax."

With the ModularMS proposal, modules are the primary design unit, and deployment is just an option. The same code can adapt to three different scenarios:

  • Modular Monolith: All modules reside in a single instance, ideal for small teams or early stages.

┌────────────────────────────────────┐
│            Application             │
│ ┌────────┐ ┌────────┐ ┌────────┐   │
│ │Module A│ │Module B│ │Module C│   │
│ └────────┘ └────────┘ └────────┘   │
└────────────────────────────────────┘

  • Independent Microservices: An independent instance for each module for granular scalability.

┌────────────┐   ┌────────────┐   ┌────────────┐
│ Module A   │   │ Module B   │   │ Module C   │
│ Service    │   │ Service    │   │ Service    │
└────────────┘   └────────────┘   └────────────┘

  • Grouped Microservices: Related modules sharing the same deployment, optimizing resource usage.

┌──────────────────┐   ┌──────────────────┐
│  Service X       │   │  Service Y       │
│ ┌────────────┐   │   │ ┌────────────┐   │
│ │ Module A   │   │   │ │ Module C   │   │
│ │ Module B   │   │   │ │ Module D   │   │
│ └────────────┘   │   │ └────────────┘   │
└──────────────────┘   └──────────────────┘

Maintaining Order with Spring Modulith and IntelliJ

For a modular architecture to be effective, boundaries must be real and verifiable. Tools like Spring Modulith integrate with IDEs like IntelliJ IDEA to offer visual validation of encapsulation. (Image 4)

While working in the development environment, you can quickly identify the status of your packages through icons: closed padlocks indicate protected internal packages, while open ones represent public APIs. If Module A tries to access an internal class from Module B, the system will immediately flag the error in red.

Technical Implementation: Profiles and ComponentScan

The magic behind ModularMS lies in the combination of defined boundaries and the strategic use of @Profile and @ComponentScan in Spring Boot.

1. Definition of Boundaries and Events

Each module manages its own logic and communicates via events to maintain decoupling. This allows communication to be transparent, whether local or distributed.


@Externalized("new-order.#{#this.productId()}")
public record OrderPlacedEvent(String productId, int quantity) { }

2. Dynamic Control via Profiles

Instead of heavy global configurations, we use profiles to activate only what is necessary. By running a specific profile command, the system only loads the required modules, allowing everything from a single microservice to a functional monolith for local testing.


@Configuration
@Profile("orders")
@ComponentScan(basePackages = "me.lbenavides.modularms.order")
public class OrdersModuleConfig { }

Advantages for Developer Experience (DX) and Business

Adopting a modular deployment is both a technical decision and an improvement in software delivery strategy:

  • Immediate Feedback: Integration tests cover full end-to-end flows in seconds, without network latency or the need to spin up multiple containers.
  • Living Documentation: The system generates automatic diagrams by analyzing the actual code, ensuring the documented architecture always matches the execution.
  • Deferred Decisions: It allows you to start simple and separate modules only when the load or team size truly demands it.

From my perspective, architecture should grow with the team, not ahead of it. With ModularMS, my goal is to demonstrate that we can maintain clean boundaries and impeccable documentation without paying the "distributed complexity tax" from day one.

Ultimately, it’s about choosing tools that allow us to focus on what really matters: delivering value agilely, without infrastructure becoming an obstacle. If you want to see how to implement this in your own projects, I invite you to explore the repository—and of course, any feedback is more than welcome!

attach icon
Attach file
maximum: 10MB
Thank you. We have received your shipment.
Oops! Something went wrong while submitting the form.

Download it for FREE here! 🇺🇸

Enter your details in the following form and get the full report.
attach icon
Adjuntar archivo
máximo: 10MB
Download the file by clicking the button
Click here
Oops! Something went wrong while submitting the form.

Create your own AI agents with Pulzen LLMApp

Es
Eng