Lab4 - CQRS, Event Sourcing & Clean Architecture

Context¶
StockMind is an inventory management product developed by a software company for retail distribution chains that operate across multiple sales channels simultaneously: e-commerce (web and mobile), physical retail (in-store point-of-sale), B2B wholesale (bulk orders from partner companies), and third-party marketplaces (Amazon, Jumia, etc.). The core challenge is that all these channels read from and write to the same stock in real time, yet they have radically different requirements. An e-commerce platform needs sub-200ms availability checks. A financial analyst needs six-month aggregated trend reports. A B2B client needs a guaranteed stock reservation that holds for 48 hours. A compliance officer needs to reconstruct the exact state of the stock on any given date in the past. StockMind is sold as a SaaS product to multiple retail chains, each with their own business rules, reservation policies, and return procedures. Your task is to design an architecture that satisfies all these requirements without compromise.
Functional Requirements¶
Stock Management¶
- Every stock movement — receipt, sale, return, inter-warehouse transfer, reservation, and cancellation — is recorded with its origin channel, timestamp, quantity, and operator identity.
- The system maintains three levels of stock per product per location: physical stock (what is physically present), available-to-sell stock (after deducting active reservations), and in-transit stock (ordered but not yet received).
- A product can be sold in multiple units (unit, box, pallet) with automatic quantity conversion.
- Stock can be managed at the warehouse level, the store level, and the regional level, with aggregation queries possible at any level of the hierarchy.
Read Access by Channel¶
- E-commerce teams require near-real-time product availability (latency < 200 ms) to display accurate stock status to online shoppers: 'In Stock', 'Only 3 left', 'Out of Stock'.
- Supply chain planners require aggregated analytical reports: stock evolution over the past 6 months, rotation rate per product, stockout forecasts, channel-by-channel breakdown.
- Physical stores require a local stock view, synchronized periodically and available offline if connectivity is lost.
- B2B wholesale clients require confirmed reservations before payment: stock is exclusively reserved for 48 hours upon order confirmation.
Alerts & Automation¶
- Automatic replenishment alerts are triggered when stock falls below a configurable threshold, defined per product and per warehouse.
- The system automatically proposes inter-warehouse transfers when one warehouse is in stockout and another holds excess inventory of the same product.
- Customer returns are automatically reintegrated into available stock after a quality validation step.
Non-Functional Requirements & Constraints¶
- Write consistency: Overselling is strictly forbidden. Two channels must never be able to sell the last unit of a product simultaneously. Strong consistency on writes is a hard requirement.
- Read availability: Read access must remain available even in the event of a partial system failure. A store must always be able to consult its local stock.
- Full audit trail: Every stock movement must be traceable for regulatory compliance. It must be possible to reconstruct the exact state of the stock at any past date and time.
- Scale: The system must support several hundred stores and several million product references.
- Performance isolation: Analytical reporting queries must not impact the performance of transactional operations.
- Domain isolation: The business logic for computing available stock is complex and subject to frequent change. It must be fully isolated from database and API concerns and independently testable.
- Multi-tenancy: StockMind serves multiple retail chains as a SaaS product. Each client has different business rules for reservations, return windows, and stock calculation. The architecture must accommodate this without code duplication.
Architecture Diagram Requirements¶
You are required to represent your architecture at multiple levels of abstraction. At minimum, provide:
(1) A system-level architecture diagram — show all bounded contexts, their interactions, the event broker, and the storage units. Every element must be explicitly labeled. Include a legend.
(2) A bounded context diagram for each of the two contexts you choose to detail — show the internal structure: aggregates, domain entities, use cases, ports, and adapters. The storage layer must be visible and justified.
(3) A synchronisation diagram — show how events flow between your two bounded contexts: what triggers each event, what it carries, and how the receiving context reacts.
You may use any architectural notation (C4 Model, ArchiMate, or informal box-and-arrow diagrams) as long as all elements are explicitly labeled and a legend is provided. UML alone is not sufficient.
Questions¶
Q1 — Bounded Context Identification¶
Analyse the requirements and identify all the bounded contexts of the StockMind system. For each one, specify:
- Its name and core responsibility
- The main aggregate(s) it owns
- Why it is a distinct context — what makes its boundary justified
You should identify at least four bounded contexts. Justify any grouping or separation decisions you make.
Q2 — Detailed Architecture of Two Bounded Contexts¶
Choose two bounded contexts that interact with each other and design their internal architecture in detail. For each one:
- Apply Clean Architecture principles: identify the domain entities, use cases, ports, and adapters. Justify why the domain layer has no dependency on the database or any external framework.
- Define the storage layer: choose an appropriate storage technology and justify your choice based on the access patterns and consistency requirements of that context. Explain whether the context uses an event store, a relational database, a document store, a cache, or a combination — and why.
- Apply CQRS where relevant: if the context has distinct read and write needs, define the write model and at least one read model. Explain what each read model is optimised for and how it is kept up to date.
Q3 — Inter-Context Synchronisation via Events¶
Define the events that enable synchronisation between your two chosen bounded contexts. For each event:
- Specify its name (past tense, e.g.
StockReserved), its trigger, and its full payload - Identify which context publishes it and which context consumes it
- Explain what the consuming context does when it receives the event — what state changes, what read models are updated, what commands may be triggered
- Identify any compensation mechanism: what happens if the consuming context fails to process the event?
Then answer: is the consistency between your two contexts strong or eventual? Justify why this is acceptable given the requirements.
Q4 — The Black Friday Scenario¶
At 11:58 PM on Black Friday, three simultaneous orders arrive from the e-commerce channel, the B2B channel, and a marketplace — each requesting the last available unit of product #SKU-4471 in warehouse W3.
Walk through exactly what happens in your architecture, step by step:
- How does your write model prevent overselling?
- What is the role of your storage layer in enforcing this guarantee?
- How do the read models of each channel get updated after the winning transaction?
- What response do the two losing channels receive, and when?