When building IT systems, we often talk about modules – independent parts of an application that can carry out specific business processes on their own. A well-designed module makes the application more flexible, easier to extend, and maintain. Such a module can also be easily extracted to separate a deployable unit (let’s call it “microservice” for simplicity). But what does “well-designed” actually mean?
Below I outline some key characteristics that define a module in modern architecture.
1. Single Responsibility Principle (SRP) – modules should be built around processes, not data
The Single Responsibility Principle (SRP), originally part of the SOLID principles in object-oriented programming, was meant for classes. In the context of architecture, we can extend it to the level of modules.
👉 The key idea is that modules should not be built around data (nouns), but around processes (verbs).
Why?
- If we design modules around data, e.g. a User module, it quickly becomes a magnet for all kinds of functionality: registration, login, authorization, profiles, preferences, etc. This creates a huge “bucket module” that is hard to maintain.
- Processes are more stable than data. Data always tempts us to add more features, while processes naturally define clear boundaries.
Example: instead of one massive User module, it’s better to split into smaller modules: User Registration, Authorization, Profile Management.
This approach also works well with the Open/Closed Principle (OCP) – a system should be open for extension but closed for modification. When adding new processes, we create a new module instead of modifying existing ones. That way, what we’ve already built continues to work as expected.
2. Encapsulation – modules protect their code and data
The second key characteristic of a module is encapsulation. A module is an independent unit that hides its internal implementation and manages its own data.
In practice, this means:
- Each module has its own database or, at minimum, its own tables/schema.
- Other modules cannot directly read or modify this data.
- When we add a new process, we create a new module with its own tables – even if that means duplicating data.
This may sound counterintuitive (“isn’t data duplication bad?”), but in modular architecture it’s a deliberate design choice. It ensures that changes inside one module never force changes in others.
3. Module API – controlled entry point
Since a module hides its implementation and data, there needs to be a way for other modules to use its functionality. That way is through the module’s API.
- Each module should expose one or two classes (or interfaces) that act as the entry point.
- Other modules can only interact through this API.
- This keeps the system clean and controlled – no sneaky direct database calls or cross-module hacks.
The API is therefore an extension of encapsulation: it shields the module while enabling collaboration.

4. Vertical Slice – modules contain all layers
The fourth characteristic of a module is the vertical slice approach. Each module should contain all three classic layers:
- Presentation (e.g. controllers, REST endpoints),
- Business logic (processes, rules),
- Persistence (repositories, data access).
That way, a module is a complete, independent unit.
👉 A crucial detail: we should not fear code duplication between modules. Each module lives independently, and changes inside it should never ripple into others.
Summary
A module in IT architecture is an independent business unit that:
- focuses on a single process (SRP for processes, not data),
- encapsulates its own code and data,
- exposes a controlled API for collaboration,
- contains all required layers (vertical slice).
With this design, we can build systems that are stable, resilient to change, and easy to extend. Instead of an ever-growing monolith, we get a collection of clearly separated, well-defined building blocks that can evolve independently.