SlideShare a Scribd company logo
Git: h'ps://github.com/victorrentea/spring-modulith.git
Branch: devoxx-uk-24
Slides: TODO
👋 I'm Victor Rentea 🇷🇴 Java Champion, PhD(CS)
18 years of coding
10 years of training & consul2ng at 130+ companies on:
❤ Refactoring, Architecture, Unit Tes4ng
🛠 Java: Spring, Hibernate, Performance, ReacIve
Lead of European So8ware Cra8ers (7K developers)
Join for free monthly online meeIngs from 1700 CET
Channel: YouTube.com/vrentea
Life += 👰 + 👧 + 🙇 + 🐈 @victorrentea
https://victorrentea.ro
🇷🇴
past events
3 VictorRentea.ro
🙋🙋
Legacy Monolith?
Microservices?
Java?
Spring?
ArchUnit?
4 VictorRentea.ro
What's faster to build from scratch?
One Monolith or 3 Microservices
... to release in 6-12 months?
5 VictorRentea.ro
What's faster to build from scratch?
One Monolith or 3 Microservices
... to release in 6-12 months?
6 VictorRentea.ro
Big Ball of Mud
(BBoM Pattern)
= a sprawling, sloppy,
duct-tape,
spaghetti-code jungle,
showing signs of unregulated growth,
and repeated expedient repair.
In desperate need of refactoring, but lacking tests.
https://wiki.c2.com/?BigBallOfMud
7 VictorRentea.ro
☢ nano-services
Velocity
⏩
FAST
🐌
SLOW
Microservices
Autonomy of microservices
outweighs their overhead
Development Velocity
☢ BBoM
Monolith My system will be complex,
so, let's start with microservices!
(Next-Ne)lix Syndrome)
Project Age
Early Late
produc3vity drops due to
high complexity & coupling
1-2 years or ≥ 7 dev
8 VictorRentea.ro
You should NOT start a new project with microservices,
even if you're sure your application will be big enough
to make it worthwhile. - Martin Fowler
principal microservice evangelist
h5ps://mar3nfowler.com/bliki/MonolithFirst.html (2015)
Instead: start simple (KISS) and
address the system's natural bottlenecks as they occur
( bugs, delays, dev pain )
😔 😔 😔
Meanwhile: "If we don't start with microservices, THEY (the bosses) won't
give us the .me we need to break it into microservices later" = WASTE
9 VictorRentea.ro
Architecture is
the art of deferring decisions
10 VictorRentea.ro
Pain-Driven Architecture
Protect core logic vs ugly API call with an Adapter
Split Complexity by Layers of Abstraction (ie. Facade)
Isolate Persistence if Shared/Legacy storage
Grow a Rich Model in Complex Domains
Refactor to Modulith when team grows
Use Events for cleaner 1:N Decoupling
Go to Microservices to meet NFRs
11 VictorRentea.ro
Monolith to Microservices
12 VictorRentea.ro
1) Big-Bang Rewrite of a 12y-old, 3M LOC codebase
- Re-gather all requirements and start from scratch
- Any changes to the old system you (a) reject, (b) delay, or (b) cost x2 (old+new)
- 20-30% success rate & likely to turn into a Distributed Monolith
2) Strangler-Fig Pa4ern (outside-in) ✅
- Rewrite decoupled parts as microservices behind a proxy protecIng clients
3) Refactor to Modules > Extract (inside-out) ✅
- Progressively decouple logic and data in the monolithic codebase
From a BBoM to Microservices
13 VictorRentea.ro
Refactor to Modules
Modulith
Can prove the best
in some domains
Velocity
⏩
FAST
🐌
SLOW
Microservices
Development Velocity
Monolith
Project Age
Early Late
Easy to extract
a microservice
14 VictorRentea.ro
Can we have the best of both?
Deployment architecture of a Monolith
Logical decoupling of Microservices
+ Easy to extract a Microservice
15 VictorRentea.ro
Modul ith
ar Monol
16 VictorRentea.ro
Modulith
17 VictorRentea.ro
Big Ball of Mud Microservices
XXL Database
eShop
Application
Catalog
Microservice
Catalog DB
Orders
Microservice
Orders DB
REST REST/MQ
Payment
Microservice
Payment DB
18 VictorRentea.ro
Modulith
ApplicaIon
Catalog
Module
Orders
Module
Payment
Module
Database
19 VictorRentea.ro
Goal of Modulith
independent teams managing decoupled modules
Example #1 (e-health)
each team {4-5 DEV+FE+PO+QA} owns ~4 modules
x 8 teams
+ 2 x FuncIonal Architects
+ 3 x Core Pladorm Team
total = 60 people
CI build ≤ 15 minutes (tuned)
1 prod deploy /week on 10 instances
Example #2 (pharmacy): 30 people
Example #3 (loan approval): 24 people
20 VictorRentea.ro
How to start?
21 VictorRentea.ro
Modulith
Code Decoupling
VictorRentea.ro
com.foo.bar.
controller
service
entity
repository
Code Par))oning
top-level packages per...
VictorRentea.ro
* h$ps://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html
Technical
layer/ring
Func)onal
sub-domain*
com.foo.bar.
catalog
inventory
order
payment
Code Partitioning
top-level packages per...
controller
service
entity
repository
com.foo.bar.
controller
service
entity
repository
24 VictorRentea.ro
= a stand-alone logical applicaEon, having its own:
§business features (user value)
§private implementaIon: domain model + logic
§public API:
- internal, for other modules: via method calls or events
- external, for other systems: via REST, Rabbit, KaOa...
§private tables in database
§micro-frontend: screens & shared components (monorepo)
What is a Module?
25 VictorRentea.ro
Internal API
for other modules
External API
for other systems
MQ
RPC
implementa4on
not accessible
by other modules
Events
publish
<< plugin >>
B
listen
Methods
Interface
26 VictorRentea.ro
§Publisher should NOT expect any effect ⚠
§Publisher is unaware of listeners (poten;ally mul;ple) J
§The order of listeners should not ma>er. If it does: chain a new event ⚠
§Events can carry state to avoid a call back to publisher 🤔
§All listeners run sequen1ally in the publisher's thread and transac;on (if any)
§Listeners can be @Async
§Events can be persisted if sent over KaJa/Rabbit..
- Spring-modulith @Applica3onModuleListener persist events in DB un3l processed
⚠ Events are harder to navigate than method calls è use only between modules
Events 101
Eventual Consistency
27 VictorRentea.ro
28 VictorRentea.ro
↙ Generated by spring-modulith
h5ps://github.com/victorrentea/spring-modulith
29 VictorRentea.ro
§ArchUnit @Test www.archunit.org + ported to most languages
§Spring Modulith @Test spring.io/projects/spring-modulith
§Build Modules (Maven/Gradle)
Enforce Code Boundaries
@Test !// unit test running on CI
public void encapsulatedModules() {
var classes = new ClassFileImporter().importPackages("com.myapp");
var sliceRule = slices().matching("!..myapp.(*)!..*")
.should().notDependOnEachOther()
.ignoreDependency(resideInAnyPackage("!..shared!..", "!..api!.."));
sliceRule.check(classes); !// #1 fail on any deviation
List<String> violations = sliceRule.evaluate(classes)!!...;
assertThat(violations).hasSizeLessThan(33); !// #2 fitness function
}
@Test
void verifyModularity() { !// uses ArchUnit rules under the hood
ApplicationModules.of(ModulithApp.class).verify();
}
30 VictorRentea.ro
⚠ Only a'er boundaries are clear AND the team is about to split
✅ Stronger separa2on
- Impossible to add excep:ons/@Disable to the ArchUnit @Tests 😏
- Impossible to have cycles è
- BeAer IDE sugges:ons (eg: imagine 2 classes named 'Product' in different modules)
✅ Selec2ve dependencies
- A module can decide to use jasperreports, use reactor, or refuse lombok
- ⚠ All modules share the SAME library VERSIONS in the final binary
✅ Par2al release
- Client customiza:ons: invoicing-nhs.jar
- Purchased features: payment-exports.jar
From Packages to Build Modules
(Maven/Gradle)
31 VictorRentea.ro
Cyclic Dependencies
« module »
A
« module »
B
= Tight Coupling (they oEen change together)
⚠ Build fails if modules are separate build units (eg maven/gradle)
use
use
32 VictorRentea.ro
?
?
A B
O
orchestrator
"facade"
Pull OrchestraIon Up
?
?
?
?
Allow the call cycle,
just fix the code cycle
shared
A-impl B-impl
A-api B-api
Extract API out
run5me calls
keep a coarse-grained API,
for a monolithic client/site
Strategical Dependencies between Modules
microservices: shared lib
microservices: events on queue
microservices: interdependent microservices + client.jar
microservices: api gateway/bff/saga microservices: shared lib/3rd service microservices: merge or break
❤
AB
Merge Modules
Tight Coupling
(eg dozens of links)
Dependency Inversion
B allows A to implement logic,
without depending on A
A B
ç event
call
Publish Events (in-mem)
⭐Decoupled
A B
S
Push Shared Down
A B
(code dep) implements è
call
Dependency Inversion
⭐Decoupled
AProviderImpl
runtime call
«interface»
AProvider
Module A must react to changes in B
"shared"
Module:
- StringUQls
- Logging/Audit
- Country list
Wrong boundaries.
Try others? 🤔
33 VictorRentea.ro
The 'Shared' Module
§If large => BBoM ☢
- Possible starIng point coming from BBoM
§Extract business logic
§Extract complex concerns: common-security, common-kaOa..
§Contain internal API of all modules: api.catalog|.inventory 🤔
- ✅ Pros: simple fix to cyclic dependencies
- ⚠ Cons: risk of coupling internal APIs (write an ArchUnit rule)
§Contain staEc reference data: Country, Region, DiagnosEc...
- Be'er than dozens of nano-modules
34 VictorRentea.ro
* the same applies for "Microservice"
Smaller! Nano!
Post-BBoM PTSD ?
How small should modules be?
or microservices
35 VictorRentea.ro
The Fallacy of Nano-Services
The microservices honeymoon is over.
Uber is refactoring thousands of microservices into a more manageable solution;
Kelsey Hightower is predicting monoliths are the future;
Sam Newman is declaring that microservices should never be the default choice,
but rather a last resort.
Monolith can be cheaper (Amazon) and faster (StackOverflow.com)
https://vladikk.com/2020/04/09/untangling-microservices/
Smaller pieces
=> more coupling
36 VictorRentea.ro
order product
fulfillment
place order
cancel order
return
catalog
search
filter
display
compare
stock
inventory
stock
warehouse
supply-chain
hEps://www.michaelnygard.com/blog/2018/01/services-by-lifecycle/
Scales
Be'er
Split by
Data Concept
(aka En*ty Service)
Bu$in€ss Capability / User Value
(aka Feature Service)
37 VictorRentea.ro
Modulith
Data Decoupling
38 VictorRentea.ro
Modules should not
share tables
Allows to keep in sync:
Problem Domain ó Domain Model ó DB
or Microservices
VictorRentea.ro
inventory
catalog
Split Domain Models
class InventoryItem {
Product product;
Long productId;
String productName;
...
}
class Product {
id
name
...
}
40 VictorRentea.ro
Data Decoupling Levels
1. No IsolaGon (BBoM): everyone freely reads/writes any table
⚠ Data CorrupIon: a module could write valid data in a table, but later read bad data.
2. Write IsolaGon: one module writes into a table, but any other can read
🧠 Might require spliong a table (in separate schemas)
INVENTORY.ITEMS vs CATALOG.PRODUCTS, CATALOG.PRODUCT_ATTRIBUTES
⚠ Frozen Table Structure: an ALTER TABLE can break the readers
3. Exclusive Access🤩💖: modules have private schemas
😏 Trick: except read-only VIEWS exposed for others to JOIN : INVENTORY.V_STOCK(id, items)
4. Consistency per Module - tables of two modules:
(a) do NOT share any Foreign Key, and
(b) are NOT updated in the same Transac4on
Defer unIl microservice
extrac4on is imminent
Strong Consistency
Eventual Consistency
41 VictorRentea.ro
(vs a tradiJonal Monolith)?
1. Complexity EncapsulaIon behind clear Module APIs
- Autonomy & Less cogniJve load per module
2. Smaller Domain Model gets specialized, thus more useful
- catalog.Product vs inventory.InventoryItem
3. Module owns its Persistence
- Easy to keep tables in sync with evolving Domain Model
What makes a Modulith maintainable
42 VictorRentea.ro
Modulith Challenges
Finding Boundaries 🔄
EncapsulaEng Code
Decoupling Data
Speed of Build & Test
OperaEon
45 VictorRentea.ro
§End-to-end tests are slow and fragile
- Prefer Module-scoped tests ✅ over fragile unit-tests ❌
§"Always ready to ship" using Feature Flags
- ⚠ Constantly remove unneeded flags
§Parallel Build 😎
§A Monorepo can build mulEple arEfacts:
- Modulith + Frontend + 2 Microservices 🤔
Unified Build
46 VictorRentea.ro
§Shared TransacIons
- An excepIon in a module you call/noIfy can roll back your transacIon
§Resource starvaIon
- Modules share thread/DB connec4on pool è Monitoring ⚠
§Deadlocks
- In-process or out- (DB, Redis)
§Single instance of DI container
- Global seongs, rogue aspects, bean name collision
§Unified OpenAPI
- Single version? Type name collisions?
DifficulFes of "Running Together"
47 VictorRentea.ro
Next Step?
Microservices!🦄
48 VictorRentea.ro
Benefits of Microservices
49 VictorRentea.ro
They are cool
😎
Benefits of Microservices
50 VictorRentea.ro
Benefits of Microservices
ü Faster Time-to-Market => 😁 Business
if independently deployable by autonomous teams
ü Lower CogniGve Load => 😁 Developers
if small & aligned with business
ü Scalability for the hot🔥 parts that require it
ü Availability: fault-tolerance to parBal failures
ü Technology Freedom vs language/library version
ü Security / Privacy (GDPR) / Compliance
Modulith also
provides these
51 VictorRentea.ro
Drawbacks of Microservices
§Complex to Develop & Deploy
§Network Latency & Reliability
§Asynchronous CommunicaGon (messages/events)
§Eventual Consistency
§Hard to Monitor, Trace & Debug
$M1 premium
52 VictorRentea.ro
§Separate persistence
- No cross-schema SELECT. 🤔 Think...
- Drop all Foreign Keys to ó from other modules' schemas 🤔
- Stop sharing transac4ons with other modules 🤔
§Separate threads
- Turn method calls into REST localhost:8080 calls 🤔 (+propagate TraceId!)
- Events: @Async, @ApplicaIonModuleListener, or via Rabbit, Kawa 🤔
§Separate build & deploy 🎉
- Extract module X internal API as a standalone library (x-api.jar)
- Then separate Git repo 🤔
Steps to Extract a Module as a Microservice
POSTPONE
UNTIL
EXTRACTING A
MICROSERVICE
IS PLANNED IN
NEAR-FUTURE
if a step makes
business panic
STOP
undo, and rethink
extracQon
54 VictorRentea.ro
§The safest & cheapest way to split a Monolith
- To experiment with boundaries & gradually enforce them
§A valid alternaEve to Microservices
- For complex domains with decent NFRs
Modular Monolith
is
55 VictorRentea.ro
Are you sure you need
Microservices?
Think again!
I was Victor Rentea,
trainer & coach for experienced teams.
Git: h'ps://github.com/victorrentea/spring-modulith.git
Branch: devoxx-uk-24
Meet me online at:

More Related Content

PPTX
Vertical Slicing Architectures
PDF
Microservice Resilience Patterns @VoxxedCern'24
PDF
Clean pragmatic architecture @ devflix
PPTX
Microservice architecture design principles
PPTX
Microservices Decomposition Patterns
PPTX
Domain Driven Design
PPTX
CQRS: Command/Query Responsibility Segregation
PPTX
Software architecture patterns
Vertical Slicing Architectures
Microservice Resilience Patterns @VoxxedCern'24
Clean pragmatic architecture @ devflix
Microservice architecture design principles
Microservices Decomposition Patterns
Domain Driven Design
CQRS: Command/Query Responsibility Segregation
Software architecture patterns

What's hot (20)

PDF
Apache Iceberg - A Table Format for Hige Analytic Datasets
PDF
DataOpsbarcelona 2019: Deep dive into MySQL Group Replication... the magic e...
PDF
실전 서버 부하테스트 노하우
PDF
All about Zookeeper and ClickHouse Keeper.pdf
PDF
Distributed Consistency.pdf
PPTX
Zuul @ Netflix SpringOne Platform
PDF
ING Container Hosting Platform - 3 years onward_with Kube_for distribution.pdf
PDF
The Joy of Testing - Deep Dive @ Devoxx Belgium 2024
PDF
쿠버네티스를 이용한 기능 브랜치별 테스트 서버 만들기 (GitOps CI/CD)
PDF
Google Kubernetes Engine (GKE)
PDF
Exploring the power of OpenTelemetry on Kubernetes
PPTX
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
PDF
The Patterns of Distributed Logging and Containers
PDF
Let's build Developer Portal with Backstage
PPTX
Squirreling Away $640 Billion: How Stripe Leverages Flink for Change Data Cap...
PDF
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
PDF
Windows Registered I/O (RIO) vs IOCP
PDF
이벤트 기반 분산 시스템을 향한 여정
PPTX
Everything You Need To Know About Persistent Storage in Kubernetes
Apache Iceberg - A Table Format for Hige Analytic Datasets
DataOpsbarcelona 2019: Deep dive into MySQL Group Replication... the magic e...
실전 서버 부하테스트 노하우
All about Zookeeper and ClickHouse Keeper.pdf
Distributed Consistency.pdf
Zuul @ Netflix SpringOne Platform
ING Container Hosting Platform - 3 years onward_with Kube_for distribution.pdf
The Joy of Testing - Deep Dive @ Devoxx Belgium 2024
쿠버네티스를 이용한 기능 브랜치별 테스트 서버 만들기 (GitOps CI/CD)
Google Kubernetes Engine (GKE)
Exploring the power of OpenTelemetry on Kubernetes
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
The Patterns of Distributed Logging and Containers
Let's build Developer Portal with Backstage
Squirreling Away $640 Billion: How Stripe Leverages Flink for Change Data Cap...
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Windows Registered I/O (RIO) vs IOCP
이벤트 기반 분산 시스템을 향한 여정
Everything You Need To Know About Persistent Storage in Kubernetes
Ad

Similar to Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024 (20)

PPTX
apidays New York 2025 - Spring Modulith Design for Microservices by Renjith R...
PDF
Micro services
PDF
The 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
PPTX
Microservices and OSGi: Better together?
PPTX
Introduction to microservices
PDF
How to grow your own Microservice?
PPTX
Breaking down a monolith
PDF
Microservices.pdf
PDF
Microservices for java architects it-symposium-2015-09-15
PDF
Microservices for Java Architects (Indianapolis, April 15, 2015)
ODP
Developing Microservices using Spring - Beginner's Guide
PDF
Microservices for java architects coders-conf-2015-05-15
PDF
Microservices for Java Architects (Madison-Milwaukee, April 28-9, 2015)
PDF
Developing microservices with Java and applying Spring security framework and...
PDF
Writing microservices in Java -- Chicago-2015-11-10
PPTX
05 microservices microdeck
PPTX
Migrate to microservices
PDF
Refactoring to a system of systems
PPTX
Cloud native-microservices
PDF
Microservice pitfalls
apidays New York 2025 - Spring Modulith Design for Microservices by Renjith R...
Micro services
The 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
Microservices and OSGi: Better together?
Introduction to microservices
How to grow your own Microservice?
Breaking down a monolith
Microservices.pdf
Microservices for java architects it-symposium-2015-09-15
Microservices for Java Architects (Indianapolis, April 15, 2015)
Developing Microservices using Spring - Beginner's Guide
Microservices for java architects coders-conf-2015-05-15
Microservices for Java Architects (Madison-Milwaukee, April 28-9, 2015)
Developing microservices with Java and applying Spring security framework and...
Writing microservices in Java -- Chicago-2015-11-10
05 microservices microdeck
Migrate to microservices
Refactoring to a system of systems
Cloud native-microservices
Microservice pitfalls
Ad

More from Victor Rentea (20)

PDF
Top REST API Desgin Pitfalls @ Devoxx 2024
PDF
Clean Code @Voxxed Days Cluj 2023 - opening Keynote
PDF
Testing Microservices @DevoxxBE 23.pdf
PPTX
From Web to Flux @DevoxxBE 2023.pptx
PPTX
Test-Driven Design Insights@DevoxxBE 2023.pptx
PDF
Profiling your Java Application
PPTX
OAuth in the Wild
PPTX
The tests are trying to tell you something@VoxxedBucharest.pptx
PDF
Software Craftsmanship @Code Camp Festival 2022.pdf
PDF
Unit testing - 9 design hints
PPTX
Extreme Professionalism - Software Craftsmanship
PDF
Clean architecture - Protecting the Domain
PDF
Refactoring blockers and code smells @jNation 2021
PDF
Hibernate and Spring - Unleash the Magic
PDF
Integration testing with spring @JAX Mainz
PDF
The Proxy Fairy and the Magic of Spring @JAX Mainz 2021
PDF
Integration testing with spring @snow one
PDF
Pure functions and immutable objects @dev nexus 2021
PDF
TDD Mantra
PDF
Definitive Guide to Working With Exceptions in Java - takj at Java Champions ...
Top REST API Desgin Pitfalls @ Devoxx 2024
Clean Code @Voxxed Days Cluj 2023 - opening Keynote
Testing Microservices @DevoxxBE 23.pdf
From Web to Flux @DevoxxBE 2023.pptx
Test-Driven Design Insights@DevoxxBE 2023.pptx
Profiling your Java Application
OAuth in the Wild
The tests are trying to tell you something@VoxxedBucharest.pptx
Software Craftsmanship @Code Camp Festival 2022.pdf
Unit testing - 9 design hints
Extreme Professionalism - Software Craftsmanship
Clean architecture - Protecting the Domain
Refactoring blockers and code smells @jNation 2021
Hibernate and Spring - Unleash the Magic
Integration testing with spring @JAX Mainz
The Proxy Fairy and the Magic of Spring @JAX Mainz 2021
Integration testing with spring @snow one
Pure functions and immutable objects @dev nexus 2021
TDD Mantra
Definitive Guide to Working With Exceptions in Java - takj at Java Champions ...

Recently uploaded (20)

PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Electronic commerce courselecture one. Pdf
PDF
Encapsulation theory and applications.pdf
PDF
KodekX | Application Modernization Development
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Encapsulation_ Review paper, used for researhc scholars
Building Integrated photovoltaic BIPV_UPV.pdf
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
“AI and Expert System Decision Support & Business Intelligence Systems”
Understanding_Digital_Forensics_Presentation.pptx
Electronic commerce courselecture one. Pdf
Encapsulation theory and applications.pdf
KodekX | Application Modernization Development
Diabetes mellitus diagnosis method based random forest with bat algorithm
MYSQL Presentation for SQL database connectivity
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Mobile App Security Testing_ A Comprehensive Guide.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Reach Out and Touch Someone: Haptics and Empathic Computing
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Digital-Transformation-Roadmap-for-Companies.pptx
NewMind AI Weekly Chronicles - August'25 Week I
Advanced methodologies resolving dimensionality complications for autism neur...
Review of recent advances in non-invasive hemoglobin estimation
Encapsulation_ Review paper, used for researhc scholars

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024

  • 2. 👋 I'm Victor Rentea 🇷🇴 Java Champion, PhD(CS) 18 years of coding 10 years of training & consul2ng at 130+ companies on: ❤ Refactoring, Architecture, Unit Tes4ng 🛠 Java: Spring, Hibernate, Performance, ReacIve Lead of European So8ware Cra8ers (7K developers) Join for free monthly online meeIngs from 1700 CET Channel: YouTube.com/vrentea Life += 👰 + 👧 + 🙇 + 🐈 @victorrentea https://victorrentea.ro 🇷🇴 past events
  • 4. 4 VictorRentea.ro What's faster to build from scratch? One Monolith or 3 Microservices ... to release in 6-12 months?
  • 5. 5 VictorRentea.ro What's faster to build from scratch? One Monolith or 3 Microservices ... to release in 6-12 months?
  • 6. 6 VictorRentea.ro Big Ball of Mud (BBoM Pattern) = a sprawling, sloppy, duct-tape, spaghetti-code jungle, showing signs of unregulated growth, and repeated expedient repair. In desperate need of refactoring, but lacking tests. https://wiki.c2.com/?BigBallOfMud
  • 7. 7 VictorRentea.ro ☢ nano-services Velocity ⏩ FAST 🐌 SLOW Microservices Autonomy of microservices outweighs their overhead Development Velocity ☢ BBoM Monolith My system will be complex, so, let's start with microservices! (Next-Ne)lix Syndrome) Project Age Early Late produc3vity drops due to high complexity & coupling 1-2 years or ≥ 7 dev
  • 8. 8 VictorRentea.ro You should NOT start a new project with microservices, even if you're sure your application will be big enough to make it worthwhile. - Martin Fowler principal microservice evangelist h5ps://mar3nfowler.com/bliki/MonolithFirst.html (2015) Instead: start simple (KISS) and address the system's natural bottlenecks as they occur ( bugs, delays, dev pain ) 😔 😔 😔 Meanwhile: "If we don't start with microservices, THEY (the bosses) won't give us the .me we need to break it into microservices later" = WASTE
  • 9. 9 VictorRentea.ro Architecture is the art of deferring decisions
  • 10. 10 VictorRentea.ro Pain-Driven Architecture Protect core logic vs ugly API call with an Adapter Split Complexity by Layers of Abstraction (ie. Facade) Isolate Persistence if Shared/Legacy storage Grow a Rich Model in Complex Domains Refactor to Modulith when team grows Use Events for cleaner 1:N Decoupling Go to Microservices to meet NFRs
  • 12. 12 VictorRentea.ro 1) Big-Bang Rewrite of a 12y-old, 3M LOC codebase - Re-gather all requirements and start from scratch - Any changes to the old system you (a) reject, (b) delay, or (b) cost x2 (old+new) - 20-30% success rate & likely to turn into a Distributed Monolith 2) Strangler-Fig Pa4ern (outside-in) ✅ - Rewrite decoupled parts as microservices behind a proxy protecIng clients 3) Refactor to Modules > Extract (inside-out) ✅ - Progressively decouple logic and data in the monolithic codebase From a BBoM to Microservices
  • 13. 13 VictorRentea.ro Refactor to Modules Modulith Can prove the best in some domains Velocity ⏩ FAST 🐌 SLOW Microservices Development Velocity Monolith Project Age Early Late Easy to extract a microservice
  • 14. 14 VictorRentea.ro Can we have the best of both? Deployment architecture of a Monolith Logical decoupling of Microservices + Easy to extract a Microservice
  • 17. 17 VictorRentea.ro Big Ball of Mud Microservices XXL Database eShop Application Catalog Microservice Catalog DB Orders Microservice Orders DB REST REST/MQ Payment Microservice Payment DB
  • 19. 19 VictorRentea.ro Goal of Modulith independent teams managing decoupled modules Example #1 (e-health) each team {4-5 DEV+FE+PO+QA} owns ~4 modules x 8 teams + 2 x FuncIonal Architects + 3 x Core Pladorm Team total = 60 people CI build ≤ 15 minutes (tuned) 1 prod deploy /week on 10 instances Example #2 (pharmacy): 30 people Example #3 (loan approval): 24 people
  • 24. 24 VictorRentea.ro = a stand-alone logical applicaEon, having its own: §business features (user value) §private implementaIon: domain model + logic §public API: - internal, for other modules: via method calls or events - external, for other systems: via REST, Rabbit, KaOa... §private tables in database §micro-frontend: screens & shared components (monorepo) What is a Module?
  • 25. 25 VictorRentea.ro Internal API for other modules External API for other systems MQ RPC implementa4on not accessible by other modules Events publish << plugin >> B listen Methods Interface
  • 26. 26 VictorRentea.ro §Publisher should NOT expect any effect ⚠ §Publisher is unaware of listeners (poten;ally mul;ple) J §The order of listeners should not ma>er. If it does: chain a new event ⚠ §Events can carry state to avoid a call back to publisher 🤔 §All listeners run sequen1ally in the publisher's thread and transac;on (if any) §Listeners can be @Async §Events can be persisted if sent over KaJa/Rabbit.. - Spring-modulith @Applica3onModuleListener persist events in DB un3l processed ⚠ Events are harder to navigate than method calls è use only between modules Events 101 Eventual Consistency
  • 28. 28 VictorRentea.ro ↙ Generated by spring-modulith h5ps://github.com/victorrentea/spring-modulith
  • 29. 29 VictorRentea.ro §ArchUnit @Test www.archunit.org + ported to most languages §Spring Modulith @Test spring.io/projects/spring-modulith §Build Modules (Maven/Gradle) Enforce Code Boundaries @Test !// unit test running on CI public void encapsulatedModules() { var classes = new ClassFileImporter().importPackages("com.myapp"); var sliceRule = slices().matching("!..myapp.(*)!..*") .should().notDependOnEachOther() .ignoreDependency(resideInAnyPackage("!..shared!..", "!..api!..")); sliceRule.check(classes); !// #1 fail on any deviation List<String> violations = sliceRule.evaluate(classes)!!...; assertThat(violations).hasSizeLessThan(33); !// #2 fitness function } @Test void verifyModularity() { !// uses ArchUnit rules under the hood ApplicationModules.of(ModulithApp.class).verify(); }
  • 30. 30 VictorRentea.ro ⚠ Only a'er boundaries are clear AND the team is about to split ✅ Stronger separa2on - Impossible to add excep:ons/@Disable to the ArchUnit @Tests 😏 - Impossible to have cycles è - BeAer IDE sugges:ons (eg: imagine 2 classes named 'Product' in different modules) ✅ Selec2ve dependencies - A module can decide to use jasperreports, use reactor, or refuse lombok - ⚠ All modules share the SAME library VERSIONS in the final binary ✅ Par2al release - Client customiza:ons: invoicing-nhs.jar - Purchased features: payment-exports.jar From Packages to Build Modules (Maven/Gradle)
  • 31. 31 VictorRentea.ro Cyclic Dependencies « module » A « module » B = Tight Coupling (they oEen change together) ⚠ Build fails if modules are separate build units (eg maven/gradle) use use
  • 32. 32 VictorRentea.ro ? ? A B O orchestrator "facade" Pull OrchestraIon Up ? ? ? ? Allow the call cycle, just fix the code cycle shared A-impl B-impl A-api B-api Extract API out run5me calls keep a coarse-grained API, for a monolithic client/site Strategical Dependencies between Modules microservices: shared lib microservices: events on queue microservices: interdependent microservices + client.jar microservices: api gateway/bff/saga microservices: shared lib/3rd service microservices: merge or break ❤ AB Merge Modules Tight Coupling (eg dozens of links) Dependency Inversion B allows A to implement logic, without depending on A A B ç event call Publish Events (in-mem) ⭐Decoupled A B S Push Shared Down A B (code dep) implements è call Dependency Inversion ⭐Decoupled AProviderImpl runtime call «interface» AProvider Module A must react to changes in B "shared" Module: - StringUQls - Logging/Audit - Country list Wrong boundaries. Try others? 🤔
  • 33. 33 VictorRentea.ro The 'Shared' Module §If large => BBoM ☢ - Possible starIng point coming from BBoM §Extract business logic §Extract complex concerns: common-security, common-kaOa.. §Contain internal API of all modules: api.catalog|.inventory 🤔 - ✅ Pros: simple fix to cyclic dependencies - ⚠ Cons: risk of coupling internal APIs (write an ArchUnit rule) §Contain staEc reference data: Country, Region, DiagnosEc... - Be'er than dozens of nano-modules
  • 34. 34 VictorRentea.ro * the same applies for "Microservice" Smaller! Nano! Post-BBoM PTSD ? How small should modules be? or microservices
  • 35. 35 VictorRentea.ro The Fallacy of Nano-Services The microservices honeymoon is over. Uber is refactoring thousands of microservices into a more manageable solution; Kelsey Hightower is predicting monoliths are the future; Sam Newman is declaring that microservices should never be the default choice, but rather a last resort. Monolith can be cheaper (Amazon) and faster (StackOverflow.com) https://vladikk.com/2020/04/09/untangling-microservices/ Smaller pieces => more coupling
  • 36. 36 VictorRentea.ro order product fulfillment place order cancel order return catalog search filter display compare stock inventory stock warehouse supply-chain hEps://www.michaelnygard.com/blog/2018/01/services-by-lifecycle/ Scales Be'er Split by Data Concept (aka En*ty Service) Bu$in€ss Capability / User Value (aka Feature Service)
  • 38. 38 VictorRentea.ro Modules should not share tables Allows to keep in sync: Problem Domain ó Domain Model ó DB or Microservices
  • 39. VictorRentea.ro inventory catalog Split Domain Models class InventoryItem { Product product; Long productId; String productName; ... } class Product { id name ... }
  • 40. 40 VictorRentea.ro Data Decoupling Levels 1. No IsolaGon (BBoM): everyone freely reads/writes any table ⚠ Data CorrupIon: a module could write valid data in a table, but later read bad data. 2. Write IsolaGon: one module writes into a table, but any other can read 🧠 Might require spliong a table (in separate schemas) INVENTORY.ITEMS vs CATALOG.PRODUCTS, CATALOG.PRODUCT_ATTRIBUTES ⚠ Frozen Table Structure: an ALTER TABLE can break the readers 3. Exclusive Access🤩💖: modules have private schemas 😏 Trick: except read-only VIEWS exposed for others to JOIN : INVENTORY.V_STOCK(id, items) 4. Consistency per Module - tables of two modules: (a) do NOT share any Foreign Key, and (b) are NOT updated in the same Transac4on Defer unIl microservice extrac4on is imminent Strong Consistency Eventual Consistency
  • 41. 41 VictorRentea.ro (vs a tradiJonal Monolith)? 1. Complexity EncapsulaIon behind clear Module APIs - Autonomy & Less cogniJve load per module 2. Smaller Domain Model gets specialized, thus more useful - catalog.Product vs inventory.InventoryItem 3. Module owns its Persistence - Easy to keep tables in sync with evolving Domain Model What makes a Modulith maintainable
  • 42. 42 VictorRentea.ro Modulith Challenges Finding Boundaries 🔄 EncapsulaEng Code Decoupling Data Speed of Build & Test OperaEon
  • 43. 45 VictorRentea.ro §End-to-end tests are slow and fragile - Prefer Module-scoped tests ✅ over fragile unit-tests ❌ §"Always ready to ship" using Feature Flags - ⚠ Constantly remove unneeded flags §Parallel Build 😎 §A Monorepo can build mulEple arEfacts: - Modulith + Frontend + 2 Microservices 🤔 Unified Build
  • 44. 46 VictorRentea.ro §Shared TransacIons - An excepIon in a module you call/noIfy can roll back your transacIon §Resource starvaIon - Modules share thread/DB connec4on pool è Monitoring ⚠ §Deadlocks - In-process or out- (DB, Redis) §Single instance of DI container - Global seongs, rogue aspects, bean name collision §Unified OpenAPI - Single version? Type name collisions? DifficulFes of "Running Together"
  • 47. 49 VictorRentea.ro They are cool 😎 Benefits of Microservices
  • 48. 50 VictorRentea.ro Benefits of Microservices ü Faster Time-to-Market => 😁 Business if independently deployable by autonomous teams ü Lower CogniGve Load => 😁 Developers if small & aligned with business ü Scalability for the hot🔥 parts that require it ü Availability: fault-tolerance to parBal failures ü Technology Freedom vs language/library version ü Security / Privacy (GDPR) / Compliance Modulith also provides these
  • 49. 51 VictorRentea.ro Drawbacks of Microservices §Complex to Develop & Deploy §Network Latency & Reliability §Asynchronous CommunicaGon (messages/events) §Eventual Consistency §Hard to Monitor, Trace & Debug $M1 premium
  • 50. 52 VictorRentea.ro §Separate persistence - No cross-schema SELECT. 🤔 Think... - Drop all Foreign Keys to ó from other modules' schemas 🤔 - Stop sharing transac4ons with other modules 🤔 §Separate threads - Turn method calls into REST localhost:8080 calls 🤔 (+propagate TraceId!) - Events: @Async, @ApplicaIonModuleListener, or via Rabbit, Kawa 🤔 §Separate build & deploy 🎉 - Extract module X internal API as a standalone library (x-api.jar) - Then separate Git repo 🤔 Steps to Extract a Module as a Microservice POSTPONE UNTIL EXTRACTING A MICROSERVICE IS PLANNED IN NEAR-FUTURE if a step makes business panic STOP undo, and rethink extracQon
  • 51. 54 VictorRentea.ro §The safest & cheapest way to split a Monolith - To experiment with boundaries & gradually enforce them §A valid alternaEve to Microservices - For complex domains with decent NFRs Modular Monolith is
  • 52. 55 VictorRentea.ro Are you sure you need Microservices? Think again!
  • 53. I was Victor Rentea, trainer & coach for experienced teams. Git: h'ps://github.com/victorrentea/spring-modulith.git Branch: devoxx-uk-24 Meet me online at: