Chapter 11 Flashcards — Modular Monolith Architecture Style

flashcards fsa modular-monolith


What is the modular monolith architecture style?
?
A single deployable unit internally divided into well-defined modules with explicit, enforced interfaces — combining the operational simplicity of a monolith with the domain-driven structure of microservices.


Where does the modular monolith sit on the architecture spectrum?
?
Between the layered monolith (no modularity, technical partitioning) and microservices (fully distributed, independent deployment). It offers domain partitioning without distributed system overhead.


How does a modular monolith differ from a layered monolith?
?
A layered monolith partitions by technical layer (Repository, Service, Controller) and allows any component to call any other in the same or lower layer. A modular monolith partitions by business domain and enforces that only a module’s public API is accessible from outside — internal packages are hidden.


What is the defining rule of module boundaries in a modular monolith?
?
Each module exposes only its public API. Internal packages, classes, and implementation details are inaccessible from other modules. This is enforced by automated fitness functions at build time, not by convention alone.


What are the three mechanisms for inter-module communication in a modular monolith?
?

  1. Direct method calls via the module’s public API facade (default, synchronous, type-safe)
  2. In-process message/event passing via an internal event bus (loose coupling, fire-and-forget)
  3. Explicit API contracts using shared DTO/interface types (enables future extraction to services)

Why is in-process module communication a performance advantage over microservices?
?
There is no network call, no serialization, no service discovery, and no network latency between modules. All inter-module calls are in-memory method invocations — several orders of magnitude faster than HTTP or gRPC across a network boundary.


What is the data topology rule for a modular monolith?
?
Each module owns its schema exclusively. No module may read or write another module’s tables directly. Cross-module data needs are satisfied through the public module API or a dedicated read projection — never via SQL joins across schemas.


What is the difference between separate schemas and separate databases in a modular monolith?
?
Separate schemas (most common): one physical database server, each module has its own named schema. Simple to operate, logical isolation enforced in code and by schema-level permissions. Separate databases: each module has its own DB instance — maximum isolation but higher operational cost, more characteristic of microservices.


How should cross-module queries be handled (e.g., show order + product name + shipping status)?
?
Three strategies: (1) API composition — call each module’s API and assemble the result in the caller; (2) read-model projection — a reporting module subscribes to domain events and maintains a denormalized read table; (3) shared read-only view — a narrow view aggregating data for reporting only (write path stays module-owned).


What tool is used to enforce module boundary fitness functions in Java?
?
ArchUnit — a Java library that lets you write unit-test-style assertions about package dependencies. For example: “no class in orders package should access a class in inventory.internal package.” Runs in CI and fails the build on violations.


What tool is used to enforce module boundary fitness functions in .NET?
?
NetArchTest — a .NET library with a fluent API for asserting namespace dependency rules. Example: “types in App.Orders should not have a dependency on App.Inventory.Internal.”


What is module boundary erosion and why is it dangerous?
?
Module boundary erosion is when developers, under time pressure, start calling a module’s internal classes directly instead of going through its public API. Without automated fitness functions, boundaries gradually collapse and the modular monolith degrades into a big ball of mud. It is the most common failure mode of this style.


What is data sharing creep and how is it mitigated?
?
Data sharing creep is when modules begin sharing database tables — initially for a single join, then for writes. Once tables are shared, module boundaries are broken at the data layer. Mitigation: enforce schema ownership with database-level permissions (each module’s DB user has write access only to its own schema) and fitness functions that detect cross-schema writes.


What makes a modular monolith a good stepping stone toward microservices?
?
If module boundaries (code and data) are strictly maintained, each module’s public API contract can become a service interface directly. The module can be extracted one at a time with minimal refactoring — the hard work of defining boundaries was already done. If boundaries erode, this stepping-stone value is lost.


What is the primary scalability limitation of the modular monolith?
?
The entire application scales as a single unit. You cannot scale individual modules independently. If one module receives 100x the traffic of others, you must scale the entire monolith (inefficient) or extract that module as a separate service. This is the definitive architectural limit that drives migration to microservices.


What is the deployment trade-off of a modular monolith?
?
Single deployment simplicity (one pipeline, one artifact) vs. no independent module deployment. A bug in any module requires a full redeployment of the entire application. Modules cannot be deployed on different cadences.


What does Conway’s Law imply for team structure in a modular monolith?
?
Teams should own modules (business domains), not technical layers. This allows a team to deliver features end-to-end within their module without coordinating with other teams — as long as their public API contract remains stable. This maps to stream-aligned teams in Team Topologies.


What organization size is the modular monolith best suited for?
?
Teams of 5–50 engineers. Below 5, a simple layered monolith is usually sufficient. Above 50, the coordination costs around shared deployments and the scalability ceiling may justify microservices.


What are the Characteristics Ratings for the modular monolith? (summarize star ratings)
?
Performance ★★★★★, Cost ★★★★★, Testability ★★★★☆, Ease of development ★★★★☆, Simplicity ★★★★☆, Overall agility ★★★☆☆, Ease of deployment ★★★☆☆, Scalability ★★☆☆☆.


Why does the modular monolith score ★★★★★ on cost?
?
Single runtime process, single database connection pool, single deployment pipeline, single monitoring target. No service mesh, no inter-service network infrastructure, no per-service container orchestration overhead. Lowest infrastructure cost of any non-trivial architecture style.


Why does the modular monolith score ★★★★☆ on testability?
?
All modules run in a single process, making integration testing straightforward — no test containers, no service stubs, no network mocking required. Module isolation testing is easy because public APIs create clean test boundaries. No distributed tracing required to debug test failures.


Why does the modular monolith score ★★☆☆☆ on scalability?
?
The entire application is a single process. Individual modules cannot be scaled independently. The only option is to scale the whole monolith horizontally, which is inefficient if load is concentrated in one domain. This is the lowest-rated characteristic and the primary architectural limitation.


When should you use a modular monolith? (give three conditions)
?
(1) Teams that find microservices operationally too complex. (2) Applications needing domain modularity but not independent module deployment. (3) Greenfield projects planning a future microservices migration — use the modular monolith as the first step to establish clean domain boundaries before distributing.


When should you not use a modular monolith? (give two conditions)
?
(1) Individual modules need to be deployed independently on different cadences. (2) Individual modules have very high and uneven scale requirements — if one module needs 10x the compute of others, independent scaling (i.e., extraction to a service) is necessary.


What language feature enforces module encapsulation in Java?
?
The Java Platform Module System (JPMS), introduced in Java 9, allows packages to be declared as internal to a module and inaccessible from outside it at the JVM level. Combined with ArchUnit for build-time checks, this provides both runtime and CI enforcement.


What is an in-process event bus and when should it be used in a modular monolith?
?
An in-process event bus (e.g., Guava EventBus, Spring ApplicationEventPublisher, MediatR) allows one module to publish events and other modules to subscribe, without direct code coupling. Use it when the interaction is fire-and-forget, when you want to decouple the publisher from knowing which modules react, or when preparing the module communication for future extraction to an async message broker.


What is a shared contracts package and what problem does it solve?
?
A shared contracts package (or “API contracts module”) contains only interface definitions, DTOs, and records used as the public API between modules. It prevents tight coupling to internal types and makes future extraction to microservices easier — the contract becomes the service’s wire format. Modules depend on contracts, not on each other’s implementations.


Rank these four styles from lowest to highest operational complexity: layered monolith, modular monolith, service-based, microservices.
?
Layered monolith (lowest) → Modular monolithService-basedMicroservices (highest). The modular monolith is the second-simplest style operationally, adding only the enforcement overhead of module boundary fitness functions.


Priority: HIGH — Chapter 11 is new to the 2nd edition; examiners and interviewers often test on the modular monolith vs. microservices trade-off.

Last Updated: 2026-05-29