👋 Hey {{first_name|there}},
The Modularity Mirage
Ask a mid-level dev what modularity means, and you’ll likely hear:
“It’s about splitting code into smaller, reusable pieces.”
“Keeping things decoupled and layered.”
“Following SOLID or domain-driven design.”
None of that is wrong.
But here’s what most developers miss:
True modularity isn’t about code structure. It’s about isolating change.
Because over time, systems don’t break where the code is ugly.
They break where change collides with rigid assumptions.
Let’s break this mindset wide open.
🧭 The Mindset Shift
From: “Let’s separate concerns”
To: “Let’s separate rates of change”
Clean code is helpful.
But systems survive because they’re designed for evolution.
Architects don’t just ask:
“What are the responsibilities?”
They ask:“What’s going to change and how often?”
That’s the real reason to modularize.
Because if two parts of your system change at different speeds, but live together in the same box, your system will start to rot from the inside.
📔 Why Most Modularization Fails
You’ve seen this before:
A “shared” package with a dozen responsibilities, updated weekly… and terrifying to touch.
A database schema tied to internal models that change constantly.
A “reusable” component that no one reuses because it’s filled with edge cases from five projects.
Why?
Because modularity based on code shape doesn’t survive reality.
The best designs treat modularity as a tool to localize volatility.
🧰 Tool: The Change Vector Map
Use this tool to redesign or evaluate a system for long-term modularity.
Step 1: Inventory your system
List major parts: services, modules, features, jobs, APIs.
Step 2: Ask: How often does this change?
Rate each as:
🔄 Frequent (weekly/monthly)
🔁 Occasional (quarterly)
🧱 Stable (rare or annual)
Step 3: Group by Change Vectors
Group components with similar change patterns into the same module or boundary.
Split apart those that change for different reasons.
Step 4: Validate against real scenarios:
Does a change in one area require deploys elsewhere?
Do different teams update different parts for different reasons?
Can this module evolve without negotiation?
If not, your modularity is cosmetic.
🔍 Example: The Core-Plus-Messy-Layers Anti-Pattern
One team I worked with had a clean, “layered” system:
Core domain module
API module
UI module
Utility layer
On paper, perfect. In reality?
The “core” changed monthly, new use cases, logic tweaks
The utility layer is bloated with random code
API changes constantly leaked into the domain
UI and backend were deeply entangled
The issue?
The layers were based on code responsibilities, not change patterns.
Once we remapped the system around volatility:
Fast-changing parts got isolated
Slow-moving logic was wrapped and versioned
APIs were designed as contracts, not pipelines
Shipping got easier. Ownership got clearer. Bugs dropped.
🛠 What Real Architects Do Instead
1. Ask Why It Changes, Not Just What It Does
A module isn’t a unit of functionality; it’s a unit of change.
Group things that evolve together. Separate things that don’t.
2. Modularize Around Evolution Boundaries
APIs vs data models
Config vs logic
UX vs rules
Business workflows vs infrastructure
Avoid co-locating code that involves different stakeholders or has distinct update cycles.
3. Design for Independent Deployment + Testing
If a “module” cannot be changed, tested, or released independently, it’s not truly modular.
✅ Mini Challenge: Run a Change Vector Review
Pick a system you’ve worked on recently.
Ask:
What changed in the last 3 months?
Did the change touch unrelated parts of the system?
What was hard to isolate or test?
Then sketch a Change Vector Map:
Circle parts that changed together
Draw boundaries around stable areas
Spot where separation could reduce coordination
This alone can surface some of the most important refactors you’ll ever make.
🎯 Want to learn how to design systems that make sense, not just work?
If you liked this issue, you’ll get even more out of the free 5-day crash course:
From Developer to Architect
It walks you through the exact mindset shifts that help devs grow into architectural roles, including how to:
Define clear system boundaries
Communicate design intent
Make confident tradeoffs
Avoid overengineering
Think in systems, not just services
Each lesson is short, practical, and designed to shift how you think, not just what you code.
👉 Join the free crash course
Delivered straight to your inbox. No fluff, just clear thinking.
👋 Wrapping Up
Modularity isn’t a coding technique. It’s a change-management strategy.
When you modularize by:
Code patterns → you create short-term order
Change vectors → you create long-term safety
So stop asking:
“How can we organize the code?”
Start asking:
“What’s going to change, and how do we isolate it?”
That’s how great systems survive.
Thanks for reading.
See you next week,
Bogdan Colța
Tech Architect Insights