← Back to Blog
·Rian

How Modularity Changes the Way We Build

1. Why Modularity Wins

Traditional software stacks feel heavy because every system wants to be a monolith.

Modulo takes the opposite stance:

Everything should be a small, replaceable block. Code is just LEGO.

When you stop treating features as “big features” and start treating them as tiny atomic pieces, everything changes:

  • Smaller merges
  • Faster iteration
  • Cleaner architecture
  • Easier onboarding
  • Better cognitive load

Let me show you a real example.


2. A Simple Event → Action Block

This is one of the smallest “atoms” from Modulo Learn’s internal prototype:

// event.ts
export interface ModuloEvent<T = any> {
  type: string
  payload: T
  timestamp: number
}

export const createEvent = <T>(type: string, payload: T): ModuloEvent<T> => ({
  type,
  payload,
  timestamp: Date.now(),
})

This tiny pattern does a few important things:

  • Gives us a universal event shape
  • Makes logging consistent
  • Makes analytics consistent
  • Feeds directly into Modulo Insight later

You don’t need a massive event bus to start—

you need a consistent shape.


3. How a Module Reacts to an Event

Here’s a tiny “mini-module” that reacts to events:

// modules/newUserBadge.ts

import { ModuloEvent } from "../event"

export const newUserBadge = {
  name: "new-user-badge",
  condition: (event: ModuloEvent) =>
    event.type === "USER_CREATED" &&
    Date.now() - event.timestamp < 1000 * 60 * 60 * 24 * 7, // 7 days

  action: (event: ModuloEvent) => {
    return {
      addBadge: "NEW_USER",
      userId: event.payload.userId,
    }
  }
}

This does 2 things:

  1. Check if the event is relevant
  2. Return a reaction

That’s it.

A “feature” becomes 20 lines of code.


4. The Smallest Possible Orchestrator

If you compose enough modules, you need a conductor:

// orchestrator.ts
import { ModuloEvent } from "./event"
import { newUserBadge } from "./modules/newUserBadge"

const modules = [newUserBadge]

export const runModules = (event: ModuloEvent) => {
  return modules
    .filter((m) => m.condition(event))
    .map((m) => m.action(event))
}

This is the entire orchestration layer.

Later you can scale it with queues, Pub/Sub, or Webhooks…

but you don’t start there.

You start with the smallest useful block.


5. Why This Scales Surprisingly Well

Modulo’s philosophy is simple:

→ Build small

→ Compose big

→ Replace freely

Because of this:

  • a solo founder can build fast
  • a team can onboard faster
  • features don’t explode in complexity
  • you don’t get trapped in your own architecture

This is how Modulo Messenger, Modulo Learn, and Modulo Insight can all share a common internal framework without becoming a monster.


6. Closing Thoughts

People talk about “clean architecture,” “DDD,” “microservices”…

but all of those concepts share one truth:

Good systems are made of small, understandable pieces.

Modulo, at its core, is not just a product ecosystem—

it’s a philosophy of compounding small units of value.

If each block is clean,

the whole system stays clean.

If each block is replaceable,

the whole system stays flexible.

If each block is shippable,

you never lose momentum.