Architecture & Progressive Scaling
Business M is built on the core principle of Progressive Scaling. By utilizing the orchestrator architecture of Framework M, the system can deploy as a highly efficient unified monolith in Indie Mode, or seamlessly decompose into a distributed, out-of-process macroservice mesh in Enterprise Mode—all without rewriting a single line of business logic.
1. Core Architecture Model: The Three-Tier Flow
Section titled “1. Core Architecture Model: The Three-Tier Flow”At its heart, the system separates high-performance infrastructure engines from domain logic using a decoupled three-tier architecture:
graph TD
User[👤 User / Frontend Client] -->|Interacts With| Business[💼 Business Logic Layer<br>business-m / libs/*]
Business -->|Requests Operations| Control[🛠️ Engine Control Panel<br>stock-keeper / book-keeper / adapters]
Control -->|Manages States & Records| Engine[⚡ Engine Layer<br>TigerBeetle / PostgreSQL / Redis / NATS / Temporal / S3 / Gotenberg]
1.1 Layer Responsibilities
Section titled “1.1 Layer Responsibilities”- The Engine Layer: Specialized infrastructure and database engines optimized for distinct tasks (e.g., TigerBeetle for financial ledger entries, PostgreSQL for relational metadata, Redis for state caching, NATS for event messaging, Temporal for durable workflows, and Gotenberg for high-fidelity document generation).
- The Engine Control Panel: Domain-specific control processes, micro-orchestrators, and standard adapters from
framework-m-standard(e.g.,stock-keeperfor inventory state controls,book-keeperfor ledger transactions validation). - The Business Logic Layer: The actual customer-facing
business-mapplication and modular domain business libraries (libs/*for finance, wms, people).
1.2 Extension & Decoupling Model
Section titled “1.2 Extension & Decoupling Model”Under this model, the boundaries remain absolute:
- The User interacts exclusively with the Business Logic Layer.
- The Business Logic Layer interacts only with the Engine Control Panel.
- The Engine Control Panel translates domain intents and manages interactions directly with the raw Engine Layer.
2. Architectural Blueprint & Component Layers
Section titled “2. Architectural Blueprint & Component Layers”Our monorepo organizes domain layers into distinct, decoupled segments:
graph TD
Gate[Desk UI Shell / Host Gateway] -->|Composition| DC_Finance[Finance Remote MFE]
Gate -->|Composition| DC_WMS[WMS Remote MFE]
DC_Finance -->|REST / API| Gateway[API Proxy Gateway]
DC_WMS -->|REST / API| Gateway
Gateway -->|Local Call / RPC| Adapters[Dependency Injection Adapters]
Adapters -->|In-Process IPC| Local[Local LocalLedgerAdapter]
Adapters -->|Out-of-Process NATS| Remote[Remote NatsLedgerAdapter]
Local --> FinanceLib[Finance Core Domain Lib]
Remote --> FinanceService[Finance Macroservice / Postgres]
1.1 The Base Host Gateway (apps/business-m)
Section titled “1.1 The Base Host Gateway (apps/business-m)”The central coordinator and UI orchestrator.
- Global Masters: Manages fundamental, cross-domain identities (such as Party, Item, Customer, Supplier, Address) in a single shared database context.
- Host Shell: Renders the React/Tamagui sidebar navigation, notifications, and micro-frontend wrappers.
1.2 Isolated Domain Libraries (libs/)
Section titled “1.2 Isolated Domain Libraries (libs/)”Core enterprise modules (WMS, Finance, People) are developed as decoupled Python libraries.
- Bounded Contexts: Each domain maintains its own database models and controllers, inheriting from
BaseDocTypeand referencing global identities securely. - Process Isolation: Every domain library is fully self-contained and testable in isolation.
1.3 Shared Interfaces (libs/m_protocols)
Section titled “1.3 Shared Interfaces (libs/m_protocols)”To enforce strict decoupling and prevent circular dependencies, domain interactions rely on Python Protocols (interfaces) and light Data Transfer Objects (DTOs):
- Domains depend exclusively on protocols, never on other domain implementations.
- Example: The WMS module relies on a
LedgerProtocolinterface to post inventory valuation adjustments. WMS remains completely unaware of whether the ledger posts via a same-process Finance library or a remote out-of-process service.
1.4 Modular Adapters (libs/m_adapters)
Section titled “1.4 Modular Adapters (libs/m_adapters)”Provides concrete implementations of shared protocols for various environments:
- Local Adapters: Handle direct in-memory method calls for single-process deployments (Indie Mode).
- NATS Adapters: Proxy calls over a secure NATS event bus using out-of-process RPC requests (Enterprise Mode).
3. Progressive Scaling Modes
Section titled “3. Progressive Scaling Modes”| Metric | Indie Mode (Monolith) | Enterprise Mode (Macroservices) |
|---|---|---|
| Process Topology | All domains loaded in a single Python process. | Each domain deployed in a dedicated Docker/Kubernetes container. |
| Communication | Direct in-memory IPC via Local Adapters. | High-throughput NATS PubSub / RPC event bus. |
| Database Structure | Single, unified production PostgreSQL instance. | Decentralized, dedicated PostgreSQL databases per macroservice. |
| UI Delivery | Vite Module Federation from python entrypoints. | Vite Module Federation with independent remote shells. |
4. Dependency Injection Pattern
Section titled “4. Dependency Injection Pattern”The monorepo switches between monolithic and macroservice configurations at bootstrap by overriding dependency-injection containers:
import osfrom framework_m.container import container
# Read deployment modemode = os.environ.get("M_MODE", "indie")
if mode == "enterprise": # 1. Import lightweight NATS proxy adapter (no domain dependency) from m_adapters.finance.ledger import NatsLedgerAdapter
# 2. Inject out-of-process proxy into the dependent module container.wms.ledger.override(NatsLedgerAdapter(bus=container.event_bus()))else: # 1. Import full domain logic locally from finance.adapters.local_ledger import LocalLedgerAdapter
# 2. Inject local in-process adapter container.wms.ledger.override(LocalLedgerAdapter())5. Regional Augmentation & Metadata Aggregation
Section titled “5. Regional Augmentation & Metadata Aggregation”Business M coordinates localization and regulatory compliance (e.g. m-india, m-regional) through decentralized metadata aggregation:
graph LR
Regional[m-india Compliance Plugin] -->|"Emit Field Metadata (GST/PAN)"| Finance[Finance Domain Owner]
Finance -->|"Bakes Schemas"| Baked[Augmented Supplier Schema]
Baked -->|"Render Form"| Gate[Host Gateway UI]
- Compliance Contribution: A regional compliance plugin (e.g.
m-india) defines localized schema additions (e.g. adding aGSTINorPANcolumn to the globalSupplierentity). - Domain Aggregation: The active domain owner (Finance) listens for regional metadata contributions and incorporates these localized fields into its
MetadataDecoratorRegistry. - Baking Schemas: The Finance module “bakes” these fields into the database schema. Only the Finance module needs to know how to validate or store these regional compliance columns.
- Compose & Render: When the Desk UI requests the
Supplierdocument, the gateway query forwards the request to the Finance service, which returns the fully baked, augmented schema. The Gateway simply renders the fields, keeping its core codebase free of regional complexity.