modular-monolith

Modular monolith with bounded contexts. Use for scalable monoliths.

7 stars

Best use case

modular-monolith is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Modular monolith with bounded contexts. Use for scalable monoliths.

Teams using modular-monolith should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/modular-monolith/SKILL.md --create-dirs "https://raw.githubusercontent.com/G1Joshi/Agent-Skills/main/skills/architecture/modular-monolith/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/modular-monolith/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How modular-monolith Compares

Feature / Agentmodular-monolithStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Modular monolith with bounded contexts. Use for scalable monoliths.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Modular Monolith

A Modular Monolith is a single deployable unit (Monolith) where the code is structured into independent modules (like Microservices) with strict boundaries. In 2025, this is the **recommended default** architecture for most startups and medium-scale apps.

## When to Use

- Starting a new project (Greenfield).
- Domain boundaries are not yet fully clear.
- Wanting the speed of simple deployment (one CI pipeline, one DB instance) but preventing "spaghetti code".
- Precursor to Microservices.

## Quick Start

```
/src
  /Modules
    /Catalog       <-- Public Interface defined here
      /Core        <-- Internals (Classes, Logic) hidden
      /API         <-- Public Contracts (DTOs)
    /Ordering
      /Core
    /Shipping
      /Core
  /Shared          <-- Infrastructure, Event Bus
```

```csharp
// Communication via In-Process Interfaces or Events
public class OrderService {
    private readonly ICatalogModule _catalog; // In-memory reference, but strict contract

    public async Task Checkout(string productId) {
        var product = await _catalog.GetProduct(productId); // Fast 0ms call
        // ...
    }
}
```

## Core Concepts

### Module Boundaries

Code in Module A cannot access internal classes of Module B. It can only use Module B's "Public API" (Interfaces/DTOs). Enforced by compiler tools (ArchUnit, NetArchTest).

### Single Deployment

Modules are compiled together into one binary/container and deployed to one server/cluster. Simplifies Ops.

### Data Isolation (Virtual)

Ideally, each module has its own DB schema (or at least different tables). Cross-module Joins are forbidden.

## Common Patterns

### In-Memory Events

Using a mediator (like MediatR in .NET or Spring Events) to decouple modules. Module A publishes `OrderCreated`, Module B listens. No Kafka needed (yet).

### Internal APIs

Defining strict interfaces that act as "Gateways" between modules. Changing the internals of Module A doesn't break Module B as long as the interface holds.

## Best Practices

**Do**:

- Force **Architecture Tests** (e.g., "Classes in `Ordering` cannot depend on `Shipping`").
- Separate **Data Schemas** logically (different schemas in Postgres).
- Treat it as "Microservices ready to be extracted".

**Don't**:

- Don't bypass boundaries "just this once".
- Don't share Domain Entities across modules (use integration DTOs).

## Advantages over Microservices

- **Zero Latency** communication.
- **Transactional Consistency** (ACID) is easier (though ideally, avoid cross-module transactions).
- **Refactoring** is cheap (IDE "Rename" works globally).

## References

- [Modular Monoliths (Kamil Grzybek)](https://github.com/kgrzybek/modular-monolith-with-ddd)
- [The Majestic Monolith](https://m.signalvnoise.com/the-majestic-monolith/)