Skip to content

Architecture Overview

Status: Draft for review

Logical architecture

flowchart TB
    subgraph Experience
      MS[Managed Next.js Sites]
      CS[Custom Sites - Custom Plan only]
      TA[Tenant Admin React App]
      PA[Platform Admin React App]
    end

    subgraph API
      PUB[Public API]
      TEN[Tenant Admin API]
      PLA[Platform Admin API]
    end

    subgraph Application[Modular NestJS Application]
      P[Platform]
      C[Capability]
      CO[Commerce]
      S[Site]
      R[CRM]
      M[Marketing]
      CH[Channel & Advertising]
      F[Finance]
      I[Integration]
      O[Operations]
      L10N[Internationalization]
    end

    subgraph Infra
      PG[(PostgreSQL)]
      RD[(Redis)]
      Q[BullMQ Workers]
      OBJ[(S3-compatible Object Storage)]
      OBS[Observability]
    end

    MS --> PUB
    CS --> PUB
    TA --> TEN
    PA --> PLA
    PUB --> Application
    TEN --> Application
    PLA --> Application
    Application --> PG
    Application --> RD
    Application --> Q
    Application --> OBJ
    Application --> OBS

Initial deployment style

A modular monolith provides one deployable backend while enforcing module boundaries in code. Background workers may be separately deployed from the same repository. This reduces distributed-system complexity during migration while preserving extraction boundaries.

Engine ownership rule

An engine owns its authoritative domain state and exposes commands/queries/events to others. Cross-engine direct table access is forbidden at the application layer even when the data shares the same PostgreSQL cluster.

Cross-cutting internationalization

Internationalization is represented as an engine because it owns locale resolution, translation lifecycle and formatting contracts, but it is also a cross-cutting invariant. Every domain engine remains responsible for declaring which of its fields/operations are translatable or locale-sensitive. Locale, currency, timezone and market are intentionally independent.