👋 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

Keep Reading