Data & State ConsistencyCRITICAL8 min deep dive

State Machine for Inventory Movements

#Finite State Machine#Event-Driven#Audit Trail#Inventory#Terminal State

The 3-Line Engineering Rule

1. THE RULE

Model multi-step business entities (inventory, orders, payments) as strict Finite State Machines with explicit transition tables.

2. WHY IT MATTERS

Free-form status columns updated with arbitrary strings lead to impossible states (e.g. shipping an item that was cancelled or refunding a returned item twice).

3. PRODUCTION FIX

Enforce transition guards, immutable state history logs, and reject illegal state transitions at both domain code and database constraints.

Architectural Blueprint & Sequence

Hover over nodes to inspect state transitions
DETERMINISTIC STATE TRANSITIONSSCRIBBLE BLUEPRINT
Finite State Machine graph showing valid transitions, guard conditions, and terminal nodes
#1

AVAILABLE

In warehouse stock

#2

RESERVED

Checkout started (TTL: 15m)

#3

ALLOCATED

Payment succeeded

#4
Terminal State

DISPATCHED

Handed to courier (TERMINAL)

#5

RELEASED

Cart expired / cancelled

Execution Sequence & Transitions
AVAILABLERESERVED[reserve()]
RESERVEDALLOCATED[payment_success]
ALLOCATEDDISPATCHED[ship_order]
RESERVEDRELEASED[timeout / cancel]
RELEASEDAVAILABLE[re-stock]

Key Engineering Takeaways

  • Declare explicit valid transitions (e.g., `RESERVED -> ALLOCATED -> DISPATCHED`).
  • Disallow transitions out of terminal states (`CANCELLED`, `COMPLETED`, `REFUNDED`).
  • Record every transition event with actor, timestamp, previous state, and reason in an audit table.
  • Use database enum types or check constraints to reject unauthorized status values.

The Problem & Production Reality

Physical inventory movements (e.g. e-commerce warehouses, fulfillment centers) cannot be rolled back with an undo button. Once an item is dispatched into a courier van, changing its database row to `CANCELLED` creates an operational disaster. Modeling lifecycles with state machines prevents illegal operations.

Anti-Pattern: Unchecked String Status Mutations

Allowing controllers to set `order.setStatus("CANCELLED")` regardless of whether the warehouse already printed shipping labels.

ANTI-PATTERN EXAMPLE (JAVA)
// ❌ ANTI-PATTERN: Direct status overwrite without validation
public void cancelOrder(String orderId) {
    Order order = orderRepo.findById(orderId);
    // If order was already SHIPPED, setting CANCELLED creates ghost inventory!
    order.setStatus("CANCELLED");
    orderRepo.save(order);
}

Production Pattern: Strongly-Typed Enum State Machine with Guards

Encapsulate states and their permissible transitions directly in an enum or dedicated state machine library.

PRODUCTION-READY CODE (JAVA)
// ✅ PRODUCTION PATTERN: Domain State Machine with Guards
public enum InventoryState {
    AVAILABLE {
        @Override
        public InventoryState transition(InventoryEvent event) {
            if (event == InventoryEvent.RESERVE) return RESERVED;
            throw new IllegalStateTransitionException(this, event);
        }
    },
    RESERVED {
        @Override
        public InventoryState transition(InventoryEvent event) {
            if (event == InventoryEvent.PAYMENT_CONFIRMED) return ALLOCATED;
            if (event == InventoryEvent.TIMEOUT || event == InventoryEvent.CANCEL) return AVAILABLE;
            throw new IllegalStateTransitionException(this, event);
        }
    },
    ALLOCATED {
        @Override
        public InventoryState transition(InventoryEvent event) {
            if (event == InventoryEvent.DISPATCH) return DISPATCHED;
            if (event == InventoryEvent.REFUND_APPROVED) return AVAILABLE;
            throw new IllegalStateTransitionException(this, event);
        }
    },
    DISPATCHED {
        @Override
        public InventoryState transition(InventoryEvent event) {
            // TERMINAL STATE: Cannot transition backwards!
            throw new IllegalStateTransitionException("Cannot cancel an order already dispatched!");
        }
    };

    public abstract InventoryState transition(InventoryEvent event);
}

Trade-off Analysis & Staff Recommendations

AspectPros / StrengthsCons / HazardsStaff Recommendation
In-Memory Enum vs Spring StateMachine LibraryEnum-based state machines are fast, zero-dependency, and compile-time verified.Spring StateMachine supports complex hierarchical nested states and persistence out of the box.Use lightweight enum state machines for < 10 states; adopt Spring StateMachine for complex workflows with dozens of sub-states.
Audit Trail StorageFull auditability of every state change for support and financial compliance.Requires writing to an append-only audit table on every transition.Always write state transition audit rows within the same local database transaction.

PR Code Review Checklist (Click to verify)