Files
ColaFlow/docs/Modular-Monolith-Architecture.md
Yaojia Wang 014d62bcc2 Project Init
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 23:55:18 +01:00

40 KiB

ColaFlow Modular Monolith Architecture Design

Version: 1.0 Date: 2025-11-02 Status: Recommended Architecture Author: Architecture Team


Executive Summary

Recommendation: Modular Monolith (NOT Microservices)

After comprehensive analysis of ColaFlow's current state, business requirements, team composition, and project timeline, I strongly recommend adopting a Modular Monolith architecture instead of microservices.

Key Decision Factors:

  • Team size: 5-8 developers (too small for microservices)
  • Project phase: Early stage (Sprint 1 of M1)
  • Domain understanding: Still evolving
  • Time-to-market: Critical (12-month timeline)
  • Current architecture: Clean Architecture + DDD already established
  • Future flexibility: Can migrate to microservices when needed

Bottom Line: Microservices would introduce 8-12 weeks of additional development time, significant operational complexity, and distributed system challenges—all without delivering meaningful value at this stage.


1. Architecture Evaluation

1.1 Current State Analysis

What's Already Working Well:

✅ Clean Architecture with clear layer separation
✅ Domain-Driven Design with well-defined aggregates
✅ CQRS pattern with MediatR
✅ Event Sourcing for audit trail
✅ Strong typing with Value Objects
✅ Repository pattern with Unit of Work
✅ Comprehensive domain events

Evidence from Code Review:

  • Domain Layer: Project, Epic, Story, WorkTask aggregates fully implemented
  • Clean separation of concerns (Domain → Application → Infrastructure → API)
  • Rich domain model with business logic encapsulation
  • Event-driven architecture already in place

Current Project Structure:

colaflow-api/
├── src/
│   ├── ColaFlow.Domain/          ✅ Complete aggregates
│   ├── ColaFlow.Application/     ✅ CQRS handlers ready
│   ├── ColaFlow.Infrastructure/  ⚙️  In progress
│   └── ColaFlow.API/             ⚙️  In progress
├── tests/
│   ├── ColaFlow.Domain.Tests/
│   ├── ColaFlow.Application.Tests/
│   └── ColaFlow.IntegrationTests/
└── ColaFlow.sln

1.2 Business Context Analysis

From product.md:

  • Vision: AI + MCP integrated project management system
  • Timeline: 12 months (6 milestones)
  • Current Phase: M1 Sprint 1 (Weeks 1-2 of 48)
  • Team Composition:
    • M1: 2 Backend, 1 Frontend, 1 QA, 0.5 Architect = 4.5 FTE
    • M2: 2 Backend, 1 Frontend, 1 AI Engineer, 1 QA = 5.8 FTE
    • Peak (M6): 8 FTE (adding Marketing, DevOps)

Critical Observation: With a small team building an MVP, speed and simplicity are paramount.

1.3 Microservices Reality Check

Question: Does ColaFlow need microservices NOW?

Let's evaluate against Martin Fowler's Microservices Prerequisites:

Prerequisite ColaFlow Status Ready?
Rapid Provisioning Manual setup No
Basic Monitoring Not yet No
Rapid Application Deployment CI/CD basic ⚠️ Partial
DevOps Culture Learning No
Mature Domain Understanding Evolving (Sprint 1!) No
Team Size (>15-20) 4-8 developers No
Distributed Systems Experience Unknown Unknown

Score: 0/7 prerequisites met → NOT ready for microservices


2. Architecture Comparison

2.1 Option A: Current Monolithic (Status Quo)

Architecture:

┌─────────────────────────────────────┐
│      ColaFlow.API (Single App)      │
│  ┌───────────────────────────────┐  │
│  │    Application Services        │  │
│  │  (CQRS Commands & Queries)    │  │
│  └───────────────┬───────────────┘  │
│  ┌───────────────▼───────────────┐  │
│  │      Domain Layer (DDD)       │  │
│  │  Project│Epic│Story│Task      │  │
│  └───────────────┬───────────────┘  │
│  ┌───────────────▼───────────────┐  │
│  │   Infrastructure Layer        │  │
│  │  EF Core │ PostgreSQL │Redis  │  │
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘
         Single Database (PostgreSQL)

Pros:

  • Simple to develop and deploy
  • Fast iteration speed
  • Easy debugging and testing
  • ACID transactions guaranteed
  • No network latency
  • Single codebase

Cons:

  • ⚠️ All modules in one application (potential coupling risk)
  • ⚠️ Limited independent scalability
  • ⚠️ Deployment is all-or-nothing
  • ⚠️ No clear module boundaries (without discipline)

Verdict: Good for MVP, but lacks clear module boundaries for future growth.


Architecture:

┌────────────────────────────────────────────────────────────────┐
│              ColaFlow.API (Single Deployment)                  │
│  ┌──────────────────────────────────────────────────────────┐ │
│  │                   API Gateway Layer                       │ │
│  │          (Controllers, SignalR Hubs, Middleware)         │ │
│  └────────────────────┬─────────────────────────────────────┘ │
│                       │                                         │
│  ┌────────────────────┴─────────────────────────────────────┐ │
│  │                  Module Orchestration                     │ │
│  │             (Cross-module Commands/Queries)              │ │
│  └──┬─────────┬─────────┬──────────┬─────────┬─────────┬───┘ │
│     │         │         │          │         │         │      │
│  ┌──▼──┐  ┌──▼──┐  ┌──▼───┐  ┌───▼──┐  ┌──▼───┐  ┌──▼──┐  │
│  │ PM  │  │ WF  │  │ User │  │ Notif│  │ Audit│  │ AI  │  │
│  │ Mod │  │ Mod │  │ Mod  │  │ Mod  │  │ Mod  │  │ Mod │  │
│  └──┬──┘  └──┬──┘  └──┬───┘  └───┬──┘  └──┬───┘  └──┬──┘  │
│     │        │        │          │        │        │       │
│  ┌──▼────────▼────────▼──────────▼────────▼────────▼─────┐ │
│  │          Shared Infrastructure Layer                   │ │
│  │   (EF Core Context, Repositories, Event Bus)          │ │
│  └────────────────────────┬──────────────────────────────┘ │
└───────────────────────────┼────────────────────────────────┘
                            │
                 ┌──────────▼──────────┐
                 │  Single Database    │
                 │    (PostgreSQL)     │
                 └─────────────────────┘

Modules:
- PM Mod    = Project Management (Project/Epic/Story/Task)
- WF Mod    = Workflow Engine
- User Mod  = User & Authentication
- Notif Mod = Notifications (SignalR)
- Audit Mod = Audit Logs & Event Store
- AI Mod    = AI Integration & MCP Server

Module Boundaries (Bounded Contexts):

ColaFlow.sln
├── src/
   ├── ColaFlow.API/                    # Entry point
   
   ├── Modules/
      ├── ProjectManagement/           # Module 1
         ├── ColaFlow.PM.Domain/
         ├── ColaFlow.PM.Application/
         ├── ColaFlow.PM.Infrastructure/
         └── ColaFlow.PM.Api/         # Internal API/Controllers
      
      ├── Workflow/                    # Module 2
         ├── ColaFlow.Workflow.Domain/
         ├── ColaFlow.Workflow.Application/
         ├── ColaFlow.Workflow.Infrastructure/
         └── ColaFlow.Workflow.Api/
      
      ├── UserManagement/              # Module 3
         ├── ColaFlow.Users.Domain/
         ├── ColaFlow.Users.Application/
         ├── ColaFlow.Users.Infrastructure/
         └── ColaFlow.Users.Api/
      
      ├── Notifications/               # Module 4
         └── ... (similar structure)
      
      ├── Audit/                       # Module 5
         └── ... (similar structure)
      
      └── AI/                          # Module 6 (MCP Server)
          └── ... (similar structure)
   
   └── Shared/
       ├── ColaFlow.Shared.Kernel/      # Shared abstractions
       ├── ColaFlow.Shared.Events/      # Cross-module events
       └── ColaFlow.Shared.Infrastructure/ # Common infra

└── tests/
    └── ... (per-module tests)

Module Communication Rules:

// ✅ ALLOWED: Module A → Module B via Application Service
public class CreateTaskCommandHandler : IRequestHandler<CreateTaskCommand>
{
    private readonly IWorkflowService _workflowService; // From Workflow module

    public async Task<TaskDto> Handle(CreateTaskCommand command)
    {
        // Validate workflow exists
        var workflow = await _workflowService.GetWorkflowAsync(command.WorkflowId);

        // Create task
        var task = Task.Create(...);
        return task;
    }
}

// ✅ ALLOWED: Module A → Module B via Domain Event
public class TaskCreatedEventHandler : INotificationHandler<TaskCreatedEvent>
{
    public async Task Handle(TaskCreatedEvent notification)
    {
        // Notification module listens to PM module events
        await _notificationService.SendTaskCreatedNotification(notification.TaskId);
    }
}

// ❌ FORBIDDEN: Direct entity reference across modules
// Module A cannot directly reference Module B's entities
// Use DTOs or Integration Events instead

Pros:

  • Clear module boundaries (future-proof for microservices)
  • Single deployment (simple ops)
  • Single database (ACID transactions, no distributed complexity)
  • Shared infrastructure (reduce duplication)
  • Independent development (teams can work on separate modules)
  • Easy to refactor (can extract to microservices later)
  • Module-level testing (better than monolith)
  • Low operational overhead (no service discovery, API gateway complexity)

Cons:

  • ⚠️ Requires architectural discipline (enforce module boundaries)
  • ⚠️ Cannot scale modules independently (but not needed yet)
  • ⚠️ Shared database (but simplifies transactions)

Verdict: BEST CHOICE for ColaFlow's current stage.


2.3 Option C: Microservices (User Request)

Architecture:

┌────────────────────────────────────────────────────────────┐
│                    API Gateway (YARP)                      │
│            (Routing, Auth, Rate Limiting)                  │
└───┬────────┬─────────┬────────┬─────────┬────────┬────────┘
    │        │         │        │         │        │
┌───▼───┐ ┌─▼───┐ ┌───▼──┐ ┌──▼────┐ ┌──▼───┐ ┌──▼────┐
│Project│ │Work-│ │User  │ │ Notif │ │ Audit│ │  AI   │
│Service│ │flow │ │Service│ │Service│ │Service│ │Service│
│       │ │Svc  │ │      │ │       │ │      │ │       │
└───┬───┘ └─┬───┘ └───┬──┘ └──┬────┘ └──┬───┘ └──┬────┘
    │       │         │       │         │       │
┌───▼───┐ ┌─▼───┐ ┌───▼──┐ ┌──▼────┐ ┌──▼───┐ ┌──▼────┐
│PG DB 1│ │PG DB│ │PG DB │ │PG DB  │ │PG DB │ │PG DB  │
│       │ │  2  │ │  3   │ │   4   │ │  5   │ │   6   │
└───────┘ └─────┘ └──────┘ └───────┘ └──────┘ └───────┘

    ┌──────────────────────────────────────┐
    │   Service Mesh / Message Bus         │
    │  (RabbitMQ/Kafka for events)         │
    └──────────────────────────────────────┘

Microservices Breakdown:

Service Responsibility Database API Endpoints
Project Service Project/Epic/Story/Task CRUD PostgreSQL 1 /api/projects/*
Workflow Service Workflow engine, state transitions PostgreSQL 2 /api/workflows/*
User Service Auth, users, teams PostgreSQL 3 /api/users/*
Notification Service SignalR, email, push PostgreSQL 4 /api/notifications/*
Audit Service Event store, audit logs PostgreSQL 5 /api/audit/*
AI Service MCP Server, AI tasks PostgreSQL 6 /api/ai/*

Pros:

  • Independent deployment per service
  • Independent scaling (e.g., scale AI service separately)
  • Technology heterogeneity (can use Python for AI service)
  • Team autonomy (each team owns a service)
  • Fault isolation (one service crash doesn't kill others)

Cons:

  • 8-12 weeks additional development time (infrastructure setup)
  • Distributed transaction complexity (Saga pattern required)
  • Network latency (inter-service calls)
  • Debugging nightmare (distributed tracing required)
  • Operational complexity (6+ services, 6+ databases, API gateway, service mesh)
  • DevOps overhead (CI/CD per service, Kubernetes, monitoring)
  • Team coordination overhead (API contracts, versioning)
  • Cost increase (infrastructure, monitoring tools)
  • Requires 15+ developers to manage effectively (ColaFlow has 4-8)

Verdict: NOT RECOMMENDED at current stage. Premature optimization.


3. Cost-Benefit Analysis

3.1 Development Time Impact

Architecture Setup Time Feature Dev Multiplier Testing Complexity Total Time to M1
Monolith 1 week 1.0x Low 8 weeks
Modular Monolith 2 weeks 1.1x Medium 9-10 weeks
Microservices 6-8 weeks 1.5-2.0x High 16-20 weeks

Analysis: Microservices would double the time to M1, pushing the entire 12-month roadmap to 18-24 months.

3.2 Operational Complexity

Aspect Monolith Modular Monolith Microservices
Deployment Single deployment Single deployment 6+ deployments
Monitoring 1 app, 1 DB 1 app, 1 DB 6 apps, 6 DBs, API gateway
Logging Centralized Centralized Distributed (ELK stack required)
Debugging Simple Simple Complex (distributed tracing)
Testing Easy Moderate Difficult (contract testing)
Infrastructure Cost $500/month $500/month $3000-5000/month

Analysis: Microservices increase operational cost by 6-10x.

3.3 Team Skill Requirements

Skill Monolith Modular Monolith Microservices
DDD & Clean Arch Have Have Have
Distributed Systems Not needed Not needed Required
Saga Pattern Not needed Not needed Required
Service Mesh Not needed Not needed Required
Kubernetes Not needed Not needed Required
API Gateway Not needed Not needed Required
DevOps Maturity Low Low High

Analysis: Team would need 3-6 months of learning before being productive with microservices.


4. Risk Assessment

4.1 Microservices Risks

Risk Probability Impact Mitigation Cost
Distributed Transaction Failures High High Implement Saga (4-6 weeks)
Network Latency Issues Medium High Caching, optimization (ongoing)
Service Discovery Failures Medium High Consul/K8s setup (2 weeks)
Debugging Complexity High Medium Distributed tracing (2 weeks)
Data Consistency Issues High High Event sourcing, eventual consistency (4 weeks)
Team Coordination Overhead High Medium Process changes (ongoing)
Deployment Pipeline Complexity High Medium CI/CD per service (4 weeks)
Monitoring Blind Spots Medium High Full observability stack (3 weeks)

Total Risk Mitigation Time: 19-23 weeks (nearly 6 months!)

4.2 Modular Monolith Risks

Risk Probability Impact Mitigation
Module Coupling Medium Medium Architecture reviews, ArchUnit tests
Shared DB Bottleneck Low Low Optimize queries, add read replicas later
All-or-nothing Deployment Low Medium Feature flags, blue-green deployment

Total Risk Mitigation: 1-2 weeks


5. Migration Path

5.1 Modular Monolith → Microservices (When Needed)

When to consider microservices:

  1. Team Size: Grows beyond 15-20 developers
  2. Traffic: Specific modules need independent scaling (>100k users)
  3. Domain Maturity: Module boundaries are stable and well-understood
  4. DevOps Maturity: Team has mastered distributed systems

Migration Strategy (Strangler Fig Pattern):

Phase 1: Modular Monolith (NOW)
┌─────────────────────────────┐
│      Single Application      │
│  [PM][WF][User][Notif][AI]  │
└─────────────────────────────┘
         Single Database

Phase 2: Extract First Service (Year 2, if needed)
┌─────────────────────────────┐       ┌──────────────┐
│   Main Application          │◄─────►│  AI Service  │
│  [PM][WF][User][Notif]      │       │  (Extracted) │
└─────────────────────────────┘       └──────────────┘
         Main Database                   AI Database

Phase 3: Extract More Services (Year 3+, if needed)
┌─────────────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
│ PM Service      │  │ WF Svc   │  │ User Svc │  │  AI Svc  │
└─────────────────┘  └──────────┘  └──────────┘  └──────────┘
    Main DB            WF DB         User DB        AI DB

Key Point: With Modular Monolith, migration is incremental and low-risk.


6. Implementation Plan: Modular Monolith

6.1 Phase 1: Restructure to Modules (Sprint 1-2)

Goal: Organize existing code into clear modules without breaking changes.

Actions:

  1. Create module folders under src/Modules/
  2. Move existing code to appropriate modules
  3. Define module contracts (DTOs, Integration Events)
  4. Add ArchUnit tests to enforce boundaries
  5. Update documentation

Time Estimate: 1-2 weeks (can be done during Sprint 1-2)

6.2 Module Structure Template

// Example: Project Management Module

ColaFlow.PM.Domain/
├── Aggregates/
   ├── ProjectAggregate/
      ├── Project.cs              # Already exists
      ├── Epic.cs                 # Already exists
      ├── Story.cs                # Already exists
      └── WorkTask.cs             # Already exists
   └── ...
├── Events/                         # Already exists
├── ValueObjects/                   # Already exists
└── Contracts/
    └── IProjectRepository.cs       # Already exists

ColaFlow.PM.Application/
├── Commands/
   ├── CreateProject/
   ├── UpdateProject/
   └── ...
├── Queries/
   ├── GetProject/
   ├── ListProjects/
   └── ...
└── DTOs/
    └── ProjectDto.cs

ColaFlow.PM.Infrastructure/
├── Persistence/
   ├── Repositories/
      └── ProjectRepository.cs
   └── Configurations/
       └── ProjectConfiguration.cs
└── Services/
    └── ... (if any)

ColaFlow.PM.Api/                    # NEW: Module API layer
├── Controllers/
   └── ProjectsController.cs
└── Extensions/
    └── ProjectModuleExtensions.cs

6.3 Module Registration Pattern

// ColaFlow.PM.Api/Extensions/ProjectModuleExtensions.cs
public static class ProjectModuleExtensions
{
    public static IServiceCollection AddProjectManagementModule(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        // Register module dependencies
        services.AddScoped<IProjectRepository, ProjectRepository>();

        // Register MediatR handlers from this module
        services.AddMediatR(typeof(CreateProjectCommand).Assembly);

        // Register module-specific services
        services.AddScoped<IProjectService, ProjectService>();

        return services;
    }
}

// ColaFlow.API/Program.cs
var builder = WebApplication.CreateBuilder(args);

// Register modules
builder.Services.AddProjectManagementModule(builder.Configuration);
builder.Services.AddWorkflowModule(builder.Configuration);
builder.Services.AddUserManagementModule(builder.Configuration);
builder.Services.AddNotificationsModule(builder.Configuration);
builder.Services.AddAuditModule(builder.Configuration);
builder.Services.AddAIModule(builder.Configuration);

6.4 Cross-Module Communication

Option 1: Application Service Integration

// Workflow module needs Project data
public class WorkflowService : IWorkflowService
{
    private readonly IMediator _mediator; // MediatR

    public async Task<Workflow> CreateWorkflowAsync(Guid projectId)
    {
        // Query Project module via MediatR
        var project = await _mediator.Send(new GetProjectByIdQuery(projectId));

        if (project == null)
            throw new NotFoundException("Project not found");

        // Create workflow
        var workflow = Workflow.Create(project.Name + " Workflow");
        return workflow;
    }
}

Option 2: Domain Events (Decoupled)

// Project module raises event
public class Project : AggregateRoot
{
    public static Project Create(...)
    {
        var project = new Project { ... };

        // Raise domain event
        project.AddDomainEvent(new ProjectCreatedEvent(project.Id, project.Name));

        return project;
    }
}

// Workflow module listens to event
public class ProjectCreatedEventHandler : INotificationHandler<ProjectCreatedEvent>
{
    private readonly IWorkflowRepository _workflowRepository;

    public async Task Handle(ProjectCreatedEvent notification, CancellationToken ct)
    {
        // Auto-create default workflow when project is created
        var workflow = Workflow.CreateDefault(notification.ProjectId);
        await _workflowRepository.AddAsync(workflow, ct);
    }
}

6.5 Module Boundary Enforcement

Use ArchUnit for automated checks:

// tests/ArchitectureTests/ModuleBoundaryTests.cs
[Fact]
public void Modules_Should_Not_Directly_Reference_Other_Modules_Entities()
{
    var architecture = new ArchLoader()
        .LoadAssemblies(typeof(Project).Assembly, typeof(Workflow).Assembly)
        .Build();

    var rule = Types()
        .That().ResideInNamespace("ColaFlow.PM.Domain")
        .Should().NotDependOnAny("ColaFlow.Workflow.Domain");

    rule.Check(architecture);
}

[Fact]
public void Modules_Should_Communicate_Via_Application_Layer()
{
    // Define allowed dependencies
    var rule = Types()
        .That().ResideInNamespace("ColaFlow.*.Application")
        .Should().OnlyDependOn("ColaFlow.*.Domain", "ColaFlow.Shared.*", "MediatR");

    rule.Check(architecture);
}

7. Technical Decisions

7.1 Database Strategy

Decision: Single Database (PostgreSQL)

Reasoning:

  • ACID transactions across modules (critical for ColaFlow)
  • No distributed transaction complexity
  • Simple backup and recovery
  • Lower infrastructure cost
  • EF Core migrations remain simple

Schema Organization:

-- Logical separation via schemas
CREATE SCHEMA project_management;
CREATE SCHEMA workflow;
CREATE SCHEMA user_management;
CREATE SCHEMA notifications;
CREATE SCHEMA audit;
CREATE SCHEMA ai;

-- Example
CREATE TABLE project_management.projects (...);
CREATE TABLE workflow.workflows (...);

Future Migration Path: If needed, can extract module databases later using:

  • Read replicas for specific modules
  • Database-per-module with eventual consistency
  • Event sourcing for cross-module data sync

7.2 Shared Infrastructure

What's Shared:

  • EF Core DbContext (single database)
  • MediatR (command/query bus)
  • Domain Event Dispatcher
  • Logging (Serilog)
  • Authentication/Authorization (JWT)
  • Caching (Redis)
  • SignalR backplane (Redis)

What's NOT Shared:

  • Domain models (each module has its own)
  • Application logic (each module independent)
  • DTOs (module-specific)

7.3 API Organization

Option 1: Single API Project (Recommended for now)

ColaFlow.API/
├── Controllers/
│   ├── ProjectsController.cs      # PM Module
│   ├── WorkflowsController.cs     # Workflow Module
│   ├── UsersController.cs         # User Module
│   └── ...
└── Program.cs

Option 2: Module-based Controllers (Future)

ColaFlow.API/
├── Modules/
│   ├── PM/
│   │   └── Controllers/
│   │       └── ProjectsController.cs
│   ├── Workflow/
│   │   └── Controllers/
│   │       └── WorkflowsController.cs
│   └── ...
└── Program.cs

Recommendation: Start with Option 1, migrate to Option 2 when team grows.


8. Performance Considerations

8.1 Module Performance

Potential Concern: "Will modules slow down the app?"

Answer: No. Modular Monolith has zero performance penalty compared to traditional monolith:

  • Same process memory space
  • No network calls between modules
  • Same database connections
  • No serialization/deserialization overhead

Performance Optimizations:

  • Use CQRS read models for complex queries
  • Cache frequently accessed data (Redis)
  • Optimize EF Core queries with .AsNoTracking()
  • Index database properly

8.2 Scalability Path

Current (M1-M3):

Single Instance (Vertical Scaling)
- 4-8 CPU cores
- 16-32 GB RAM
- Can handle 10,000+ concurrent users

Future (M4-M6, if needed):

Horizontal Scaling (Multiple Instances)
┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│ Instance 1  │   │ Instance 2  │   │ Instance 3  │
│ ColaFlow    │   │ ColaFlow    │   │ ColaFlow    │
└──────┬──────┘   └──────┬──────┘   └──────┬──────┘
       └──────────────────┴──────────────────┘
                         │
                  ┌──────▼──────┐
                  │ PostgreSQL  │
                  │ (Primary)   │
                  └─────────────┘

Scaling Strategy:

  1. Stateless design (already done with JWT)
  2. Redis for session/cache (shared across instances)
  3. Load balancer (Nginx/Azure Load Balancer)
  4. Database read replicas (if needed)

Can scale to 100,000+ users without microservices.


9. Comparison Matrix

Criteria Monolith Modular Monolith Microservices
Development Speed
Operational Complexity
Module Boundaries
Independent Deployment
Independent Scaling
Team Independence
Testability
Transaction Support
Debugging Experience
Future Flexibility
Infrastructure Cost
Team Skill Required (High)
Best for Team Size 1-5 5-15 15+
Best for User Scale <10k <100k 100k+

Winner: Modular Monolith (Best balance for ColaFlow)


10. Final Recommendation

Reasons:

  1. Right Size for Team:

    • Team: 4-8 developers → Perfect for Modular Monolith
    • Microservices require 15-20+ developers to manage effectively
  2. Right Time in Lifecycle:

    • Current: Sprint 1 of M1 (Week 1-2 of 48)
    • Domain understanding: Still evolving
    • Microservices work best when domains are stable
  3. Right Technical Foundation:

    • Already using Clean Architecture + DDD + CQRS
    • Modular Monolith is natural next step
    • Can migrate to microservices when needed (Strangler Fig)
  4. Time-to-Market:

    • Modular Monolith: +1-2 weeks to restructure
    • Microservices: +8-12 weeks for infrastructure
    • Critical: Don't blow the 12-month M6 timeline
  5. Cost Efficiency:

    • Modular Monolith: $500/month infrastructure
    • Microservices: $3000-5000/month infrastructure
    • Team learning curve: 3-6 months for microservices
  6. Risk Management:

    • Modular Monolith: Low operational risk
    • Microservices: High risk of distributed system failures
  7. Business Value:

    • Modular Monolith: Focus on features
    • Microservices: Focus on infrastructure

Why NOT Microservices Now:

  • Team too small (4-8 vs. required 15+)
  • Domain boundaries not yet stable
  • No distributed systems experience
  • Would delay M6 launch by 6-12 months
  • 10x operational complexity increase
  • No business justification at current scale

When to Revisit:

  • Team grows to 15+ developers
  • User base exceeds 50,000 active users
  • Specific modules need independent scaling
  • Domain boundaries have been stable for 1+ year
  • Team has gained distributed systems expertise

11. Implementation Roadmap

Sprint 1-2 (Current): Module Restructuring

Week 1-2 Activities:

  1. Create module folder structure
  2. Move existing Domain/Application code to modules
  3. Define module contracts (interfaces, DTOs)
  4. Add ArchUnit tests for boundary enforcement
  5. Update documentation

Deliverables:

  • Clear module boundaries established
  • No breaking changes to existing functionality
  • Automated architecture tests in place
  • M1 Sprint 1 goals still met on time

Sprint 3-4 (M1 Completion): Module Refinement

Week 3-8 Activities:

  1. Implement cross-module communication patterns
  2. Refine module APIs
  3. Add module-specific tests
  4. Document module interaction patterns
  5. Complete M1 features in modular structure

Deliverables:

  • All M1 features complete in modular architecture
  • Module communication patterns established
  • Documentation updated

M2-M6: Evolve Modules

As Project Grows:

  1. Add new modules as needed (AI module in M2-M3)
  2. Refine boundaries based on experience
  3. Consider extraction to microservices (M5-M6, if needed)

12. Architecture Decision Record (ADR)

Decision: Adopt Modular Monolith Architecture (NOT Microservices)

Status: Recommended

Context:

  • ColaFlow is in early development (Sprint 1 of M1)
  • Team: 4-8 developers
  • Timeline: 12 months to M6 launch
  • Current architecture: Clean Architecture + DDD + CQRS (working well)
  • User request: Evaluate microservices

Decision: Use Modular Monolith architecture with clear module boundaries:

  • Single deployment unit
  • Single database
  • Modules: PM, Workflow, User, Notification, Audit, AI
  • Communication via MediatR and Domain Events
  • Enforced boundaries via ArchUnit tests

Consequences:

Positive:

  • Fast development velocity maintained
  • Simple operations (single deployment)
  • ACID transactions across modules
  • Easy debugging and testing
  • Low infrastructure cost
  • Future migration path to microservices preserved

Negative:

  • Requires architectural discipline
  • Cannot scale modules independently (not needed yet)
  • All-or-nothing deployment (mitigated with feature flags)

Alternatives Considered:

  1. Traditional Monolith → Rejected (lacks clear boundaries)
  2. Microservices → Rejected (too complex for current stage)

Decision Date: 2025-11-02

Revisit Date: After M3 completion (Week 24) or when team exceeds 15 developers


13. Migration Guide: Current → Modular Monolith

Step-by-Step Migration Plan

Current Structure:

colaflow-api/src/
├── ColaFlow.Domain/
├── ColaFlow.Application/
├── ColaFlow.Infrastructure/
└── ColaFlow.API/

Target Structure:

colaflow-api/src/
├── Modules/
│   ├── ProjectManagement/
│   │   ├── ColaFlow.PM.Domain/
│   │   ├── ColaFlow.PM.Application/
│   │   ├── ColaFlow.PM.Infrastructure/
│   │   └── ColaFlow.PM.Api/
│   ├── Workflow/
│   ├── UserManagement/
│   ├── Notifications/
│   ├── Audit/
│   └── AI/
├── Shared/
│   ├── ColaFlow.Shared.Kernel/
│   ├── ColaFlow.Shared.Events/
│   └── ColaFlow.Shared.Infrastructure/
└── ColaFlow.API/ (Entry point)

Migration Steps:

Phase 1: Create Module Projects (Week 1)

# Create module folders
cd colaflow-api/src
mkdir -p Modules/ProjectManagement
mkdir -p Modules/Workflow
mkdir -p Modules/UserManagement
mkdir -p Modules/Notifications
mkdir -p Modules/Audit
mkdir -p Modules/AI

# Create projects for PM module
dotnet new classlib -n ColaFlow.PM.Domain -o Modules/ProjectManagement/ColaFlow.PM.Domain
dotnet new classlib -n ColaFlow.PM.Application -o Modules/ProjectManagement/ColaFlow.PM.Application
dotnet new classlib -n ColaFlow.PM.Infrastructure -o Modules/ProjectManagement/ColaFlow.PM.Infrastructure
dotnet new classlib -n ColaFlow.PM.Api -o Modules/ProjectManagement/ColaFlow.PM.Api

# Repeat for other modules...

Phase 2: Move Existing Code (Week 1-2)

# Move Project aggregate to PM module
mv ColaFlow.Domain/Aggregates/ProjectAggregate/* \
   Modules/ProjectManagement/ColaFlow.PM.Domain/Aggregates/

# Move Project commands/queries to PM module
mv ColaFlow.Application/Commands/Projects/* \
   Modules/ProjectManagement/ColaFlow.PM.Application/Commands/

# Move Project controllers to PM API
mv ColaFlow.API/Controllers/ProjectsController.cs \
   Modules/ProjectManagement/ColaFlow.PM.Api/Controllers/

# Update namespaces
# (Use IDE refactoring or sed scripts)

Phase 3: Add Module Registration (Week 2)

// Modules/ProjectManagement/ColaFlow.PM.Api/ServiceCollectionExtensions.cs
public static IServiceCollection AddProjectManagementModule(
    this IServiceCollection services)
{
    services.AddScoped<IProjectRepository, ProjectRepository>();
    services.AddMediatR(typeof(CreateProjectCommand).Assembly);
    return services;
}

// ColaFlow.API/Program.cs
builder.Services.AddProjectManagementModule();
builder.Services.AddWorkflowModule();
// ... other modules

Phase 4: Add Architecture Tests (Week 2)

// tests/ArchitectureTests/ModuleBoundaryTests.cs
[Fact]
public void Modules_Should_Not_Reference_Other_Modules_Directly()
{
    // Use ArchUnit or NetArchTest
    var architecture = Architecture.LoadAssemblies(...);
    var rule = Classes()
        .That().ResideInNamespace("ColaFlow.PM.*")
        .Should().NotDependOnAny("ColaFlow.Workflow.*");

    rule.Check(architecture);
}

Estimated Time: 1-2 weeks (parallel with Sprint 1 feature work)


14. Success Metrics

How to Measure Success of Modular Monolith

M1 (Week 8):

  • All modules have clear boundaries (ArchUnit tests passing)
  • No direct cross-module entity references
  • M1 features delivered on time
  • No performance degradation

M2 (Week 16):

  • New AI module added without breaking existing modules
  • Cross-module communication via events working smoothly
  • Module-level test coverage >80%

M3 (Week 24):

  • Development velocity maintained or improved
  • Module independence validated (can develop in parallel)
  • Technical debt remains low

M6 (Week 48):

  • All 6 modules operational and stable
  • Codebase organized and maintainable
  • Ready for potential microservices extraction (if needed)

15. Conclusion

Summary

User Request: "Use microservices architecture"

Architect Response: "Not yet. Use Modular Monolith now, microservices later (if needed)."

Reasoning:

  1. Team Size: Too small (4-8 vs. required 15+)
  2. Project Phase: Too early (Sprint 1 of 48)
  3. Domain Maturity: Still evolving
  4. Cost: 10x infrastructure increase
  5. Time: +8-12 weeks delay
  6. Risk: High operational complexity

Recommended Path:

Sprint 1-2:  Restructure to Modular Monolith    ✅ (Current)
M1-M3:       Validate module boundaries         ⏳ (Next)
M4-M6:       Mature the architecture            ⏳ (Future)
Year 2+:     Consider microservices (if needed) ❓ (TBD)

Key Message: Modular Monolith gives you 90% of microservices benefits with 10% of the complexity.


16. References & Further Reading

Books:

  • "Monolith to Microservices" by Sam Newman
  • "Building Evolutionary Architectures" by Ford, Parsons, Kua
  • "Domain-Driven Design" by Eric Evans

Articles:

  • Martin Fowler: "Microservices Prerequisites"
  • Simon Brown: "Modular Monoliths"
  • Kamil Grzybek: "Modular Monolith Architecture"

Case Studies:

  • Shopify: Stayed with modular monolith (40M+ users)
  • GitHub: Extracted microservices only after 10+ years
  • StackOverflow: Monolith serving 100M+ users

Key Insight: Most successful companies start with monoliths and only move to microservices when they have a clear business justification.


Document Status: Complete - Ready for Implementation Next Review: After Sprint 2 (Week 4) Owner: Architecture Team Last Updated: 2025-11-02 Recommended Decision: ADOPT MODULAR MONOLITH ARCHITECTURE