Engineering Journal
Scaling RM and FG Inventory with Domain-Driven Services
Most inventory systems fail for one reason: they model stock as a single number.

In apparel and processing environments, that does not work. The same SKU behaves differently by buyer PO, lot, shade, factory date, and quality state. On top of that, planning, production, warehouse, and dispatch all update inventory with different expectations.
Problem
Across implementations, we repeatedly saw these gaps:
- Raw material and finished goods were treated as generic stock without buyer PO and lot context.
- Material request creation and warehouse allocation were tightly coupled, making retries unsafe.
- Teams manually reconciled physical stock and system stock during exceptions.
- Planning teams saw optimistic availability that was not yet truly allocated.
Architecture
We split responsibilities into bounded contexts:
- RM Service: inward, buyer PO binding at GRN, lot tracking, quality hold, consumption intent.
- FG Service: production intake, pack-level identifiers, dispatch-ready states.
- MES Material Request Service: request lifecycle, async retries, and operational statuses.
- WMS Allocation Service: stock authority, allocation and freeze workflows, and dispatch execution.
- Ledger Service: immutable movement history for audit and reconciliation.
Each service exposed APIs and emitted events for downstream consumers with idempotent request identifiers.
Key Design Decisions
1. Inventory as movements, not mutable balances
Instead of only storing current quantity, we persisted every stock movement.
Benefits:
- Better auditability.
- Easier reconciliation.
- Time-based reporting (point-in-time stock, aging, throughput).
2. Request and allocation as separate lifecycles
A material request was treated as a stateful resource:
wh-request-not-createdwh-request-createdallocation-in-progressallocated-frozendispatchedclosed
This removed hidden coupling between planning and warehouse operations and made failure handling explicit.
3. Idempotent integration with async retry
For every request to WMS, we used a stable transaction/reference ID and replay-safe handlers.
This was essential for reliability during retries, transient network failures, and job reruns.
Implementation Notes
- Built core APIs in NestJS and supported selected modules in Spring Boot where platform standards required it.
- Used PostgreSQL for transactional integrity and indexing-heavy query paths.
- Added Redis locks for concurrency-safe allocation paths.
- Added Swagger contracts for cross-team integration clarity.
- Added approval-governed PO-to-PO transfer flow for cancellation/date-change scenarios.
- Supported configurable validations like same-buyer and same-lot checks where required by operations.
Outcomes
- Improved stock accuracy and traceability across RM and FG layers.
- Enabled lot-aware and buyer-aware allocation decisions.
- Reduced reconciliation effort by maintaining request-to-allocation lineage.
- Reduced operational exceptions by making every movement and transfer explainable.
What I’d Recommend If You Are Building Similar Systems
- Model inventory events first, then derive balances.
- Keep warehouse as stock source of truth, even when MES initiates requests.
- Separate request intent from physical movement and dispatch confirmation.
- Add deterministic idempotency and retry behavior from day one.
Executive Snapshot
Inventory scale comes from modeling movements and authority boundaries, not from storing a single mutable stock number.
Traceability
Lot + Buyer AwareMovement-led modeling improved reconciliation and auditability.Allocation Reliability
HigherSeparated request and allocation lifecycles made retries safe.Operational Stability
ImprovedIdempotent integration reduced exception-driven firefighting.Domain Decomposition
RM, FG, request, allocation
Inventory responsibilities were split into bounded contexts with explicit ownership.
Lifecycle Modeling
Stateful request design
Request creation, allocation, freeze, and dispatch states were represented independently.
Resilience Layer
Idempotency and replay safety
Stable identifiers and deterministic handlers protected operations during retries and reruns.
