Software Archetypes

Enterprise Patterns

Language-agnostic tutorials based on "Enterprise Patterns and MDA" by Jim Arlow & Ila Neustadt

Software Archetypes is an open reference for the data patterns that underpin almost every business system: how to model people and organizations, products and catalogs, orders, payments, inventory and shipments. Each pattern starts from a real problem, walks through the structure with a UML class diagram, then shows the SQL schema, the lifecycle as a state machine, and the invariants that must hold at runtime.

The patterns are based on Jim Arlow and Ila Neustadt's Enterprise Patterns and MDA, refined with two decades of building production systems. They're written for backend engineers and architects who want a starting point that's been battle-tested across industries — not a textbook abstraction, but a working data model you can lift into PostgreSQL, MySQL or any RDBMS today.

All examples ship with working implementations in PHP, Java and TypeScript. Each pattern is roughly 10–15 minutes of reading and a self-contained mental model you can apply on its own or compose with the others.

Overview

Each pattern is presented with:

  • Problem statement — When you need this pattern
  • Conceptual overview — Core idea
  • Structure — Mermaid class diagrams
  • Behaviors — Pseudocode for operations
  • State machines — Lifecycle diagrams
  • Invariants — Business rules that must hold
  • SQL schema — ANSI SQL for persistence
  • Design considerations — Trade-offs and alternatives

Pattern Catalog

Party Archetype (Who)

Pattern File Description
Party 01-party-pattern.md Person or Organization abstraction
Party Role 02-party-role-pattern.md Customer, Supplier, Employee roles
Party Relationship 03-party-relationship-pattern.md Employment, Ownership, Marriage
Party Identifier 04-party-identifier-pattern.md PESEL, NIP, Passport, Tax ID

Product Archetype (What)

Pattern File Description
Product 05-product-archetype.md ProductType → Product → ProductInstance

Transaction Patterns (Commerce)

Pattern File Description
Order 06-order-archetype.md Order + OrderLine, lifecycle
Payment 07-payment-pattern.md Payments and Refunds
Inventory 08-inventory-pattern.md Stock tracking, transactions
Shipment 09-shipment-pattern.md Physical delivery, tracking

Pattern Relationships

ORDER (Commerce)

places

contains

references

paid by

reserves

shipped as

issued on ship

plays role in

PARTY (Who)

Person

Organization

PartyRole
(Customer / Supplier)

Customer

Order

OrderLine

Product
Catalog

Payment

Inventory

Shipment

End-to-End Integration Scenario

This walkthrough shows how all patterns connect in a typical e-commerce flow: a customer places an order, pays, stock is reserved, and the order is shipped.

1. Party Setup

// Jan Kowalski is registered as a Person with a Customer role
jan = new Person(firstName: "Jan", lastName: "Kowalski")
jan.addIdentifier(PESEL, "85031512345")
jan.addAddress(homeAddress)

customerRole = new Customer(
    party: jan,
    customerNumber: "CUST-00001234",
    loyaltyTier: LoyaltyTier.Gold,
    creditLimit: Money(1000000, "PLN")
)

2. Order Placement

order = new Order(
    orderNumber: "ORD-2026-000042",
    customer: customerRole,
    currency: "PLN",
    billingAddress: jan.getPrimaryAddress()
)

order.addLine(thinkpad, quantity: 1, unitPrice: Money(649900, "PLN"))
order.addLine(mouse,    quantity: 2, unitPrice: Money(44900, "PLN"))
// order.grandTotal = 909633 (with 23% VAT)

order.confirm()
// emits OrderConfirmed → triggers inventory reservation

3. Inventory Reservation

// Listener handles OrderConfirmed event
for line in order.lines:
    item = findInventoryItem(line.product, warehouse)
    item.reserve(line.quantity, order.orderNumber, "Order reservation")
    // emits StockReserved

// Warehouse state:
// ThinkPad: onHand=20, reserved=1, available=19
// Mouse:    onHand=50, reserved=2, available=48

4. Payment

payment = new Payment(
    reference: "PAY-2026-000089",
    order: order,
    amount: order.grandTotal,
    method: PaymentMethod.Card
)

payment.markProcessing()
// ... gateway webhook: payment.success ...
payment.complete("gw_txn_abc123")
// emits PaymentCompleted → triggers shipment creation

order.markPaid(payment)
// emits OrderPaid

5. Shipment Creation & Warehouse Flow

shipment = Shipment.fromOrder(order, "SHP-2026-000018", warehouseAddress)
shipment.addItemFromOrderLine(order.lines[0], 1)  // ThinkPad
shipment.addItemFromOrderLine(order.lines[1], 2)  // Mouse

shipment.startPicking()     // warehouse staff collects items
shipment.markPacked()       // items boxed
shipment.assignCarrier(dhl, "1234567890")
shipment.markLabelPrinted()
shipment.handOverToCarrier()
// emits ShipmentShipped

6. Inventory Issue

// Listener handles ShipmentShipped event
for item in shipment.items:
    inv = findInventoryItem(item.product, warehouse)
    inv.shipReserved(item.quantity, order.orderNumber)
    // emits StockIssued

// Warehouse state:
// ThinkPad: onHand=19, reserved=0, available=19
// Mouse:    onHand=48, reserved=0, available=48

7. Delivery

// Carrier webhook updates
shipment.markInTransit("Warszawa Hub")
shipment.markOutForDelivery()
shipment.markDelivered({ signature: "J. Kowalski" })
// emits ShipmentDelivered

order.markDelivered()
order.complete()
// emits OrderCompleted

Event Flow Summary

ShipmentInventoryPaymentOrderCustomerShipmentInventoryPaymentOrderCustomerplace orderconfirm()OrderConfirmedreserve()initiate paymentcomplete()PaymentCompletedmarkPaid()create shipmentpick → pack → label → handoverShipmentShippedshipReserved()inTransit → deliveredShipmentDeliveredcomplete()

Common Design Principles

IDs and Keys

  • Primary key: UUID v7 (time-sortable)
  • Business key: Human-readable (ORD-2024-000001)
  • External key: From other systems (gateway transaction ID)

Money

// NEVER use floating point!
// Store in smallest currency unit (cents, grosze)

amount_cents: 19999  // = 199.99
currency: "PLN"

Time

  • Timestamps: UTC, immutable (createdAt)
  • Dates: Local date without time (birthDate)
  • Validity period: validFrom/validTo for time-bounded entities

Inheritance Strategies

Strategy Use Case SQL
Single Table Few subtype fields One table, type column
Joined Many subtype-specific fields Base + subtype tables
Concrete Completely different subtypes Separate tables

Domain Events Catalog

Every pattern emits domain events when important state changes occur. These events enable loose coupling between patterns (e.g., OrderConfirmed triggers inventory reservation).

Party Domain

Event Source Trigger Payload
CustomerTierUpgraded Party Role Customer.upgradeTier() customer, previousTier, newTier
EmployeePromoted Party Role Employee.promote() employee, previousPosition, newPosition
RelationshipTerminated Party Relationship PartyRelationship.terminate() relationship, endDate, reason
EmployeePromoted Party Relationship Employment.promote() employment, previousTitle, newTitle
EmployeeTransferred Party Relationship Employment.transfer() employment, newDepartment, newLocation
OwnershipChanged Party Relationship Ownership.adjustOwnership() ownership, previousPct, newPct
IdentifierVerified Party Identifier PartyIdentifier.verify() identifier, verifier
IdentifierRevoked Party Identifier PartyIdentifier.revoke() identifier, reason

Product Domain

Event Source Trigger Payload
ProductDiscontinued Product Product.discontinue() product
InstanceSold Product ProductInstance.sell() instance, order

Commerce Domain

Event Source Trigger Payload
OrderConfirmed Order Order.confirm() order
OrderPaid Order Order.markPaid() order, payment
OrderCancelled Order Order.cancel() order, reason
PaymentProcessing Payment Payment.markProcessing() payment
PaymentCompleted Payment Payment.complete() payment
PaymentFailed Payment Payment.fail() payment, reason
PaymentCancelled Payment Payment.cancel() payment

Fulfillment Domain

Event Source Trigger Payload
StockReceived Inventory InventoryItem.receive() item, quantity, reference
StockIssued Inventory InventoryItem.issue() item, quantity, reference
StockReserved Inventory InventoryItem.reserve() item, quantity, reference
StockReleased Inventory InventoryItem.release() item, quantity, reference
StockAdjusted Inventory InventoryItem.adjust() item, quantity, reference
StockTransferred Inventory InventoryService.transfer() source, destination, quantity, reference
ShipmentShipped Shipment Shipment.handOverToCarrier() shipment
ShipmentDelivered Shipment Shipment.markDelivered() shipment
ShipmentReturned Shipment Shipment.markReturned() shipment
ShipmentCancelled Shipment Shipment.cancel() shipment

Key Event Chains

Trigger Event Typical Listener Action
OrderConfirmed Reserve inventory for each order line
OrderCancelled Release inventory reservations
PaymentCompleted Mark order as paid, create shipment
ShipmentShipped Issue reserved stock from inventory
ShipmentDelivered Mark order as delivered
ShipmentReturned Create return record, restock inventory

Rendering Mermaid Diagrams

These tutorials use Mermaid for diagrams. To render them:

  1. GitHub — Renders automatically in Markdown files
  2. VS Code — Install "Markdown Preview Mermaid Support" extension
  3. Online — Use mermaid.live
  4. CLI — Use mmdc (mermaid-cli)

Working Implementations

Three complete implementations available in a separate repository: software-archetypes-examples

Stack Directory Run
PHP 8.3 / Symfony 7 / Doctrine ORM 3 php/ cd php && make up && make demo
Java 21 / Spring Boot 3.4 / JPA+Hibernate java/ cd java && make up && make demo
TypeScript / Node 22 / TypeORM 0.3 nodejs/ cd nodejs && make build && make demo

Each demo creates the same scenario: Jan Kowalski (Person) places an order at Acme (Organization), pays by card, stock is reserved and shipped via DHL, and delivered.

Glossary

Term Definition
Archetype A recurring, universal pattern in business modeling. Archetypes (Party, Product, Order) appear across virtually every enterprise system regardless of industry.
Party An abstraction for any entity — person or organization — that can participate in transactions, hold roles, or enter relationships.
Person A concrete Party subtype representing an individual human being.
Organization A concrete Party subtype representing a company, institution, or group.
Party Role A function or capacity in which a Party acts within the system (Customer, Supplier, Employee). Separates identity from capability.
Party Relationship A directed connection between two Parties with its own attributes and lifecycle (Employment, Ownership, Marriage).
Party Identifier An external identity code assigned to a Party by an issuing authority (PESEL, NIP, Passport).
ProductType A category or template that defines the structure (attributes, rules) for a group of products. Forms a hierarchy (Electronics > Laptops).
Product A catalog item with a SKU and price that can be ordered. Belongs to a ProductType.
ProductInstance A specific physical or serialized unit of a Product, tracked individually (by serial number, batch, expiry).
Order A commercial transaction recording what a Customer wants to buy, with header info and line items.
OrderLine A single item within an Order: product, quantity, unit price, and calculated totals.
Payment A financial transaction representing money moving in (payment) or out (refund). Has its own lifecycle independent of Order.
Refund A Payment with isRefund = true, linked to the original payment. Models money returning to the customer.
InventoryItem Stock of a specific Product at a specific Location. Tracks on-hand, reserved, and available quantities.
InventoryTransaction An immutable ledger entry recording a stock change (receipt, issue, reserve, release, adjustment, transfer).
Location A physical or virtual place where inventory is stored, forming a hierarchy (Warehouse > Zone > Aisle > Bin).
Shipment The physical movement of goods from origin to destination. Has its own lifecycle separate from Order.
ShipmentEvent A timestamped status change in a Shipment's journey (picked up, in transit, delivered).
Carrier A shipping provider (DHL, UPS, InPost) with tracking integration.
Money A value object representing a monetary amount stored as an integer in the smallest currency unit (cents/grosze) plus a currency code. Never use floating point.
Domain Event A notification emitted when something significant happens (OrderConfirmed, PaymentCompleted). Used for loose coupling between patterns.
Invariant A business rule that must always be true (e.g., "reserved cannot exceed on-hand"). Enforced by preconditions and database constraints.
Precondition A condition checked before an operation executes (require). Throws an error if violated.
EAV Entity-Attribute-Value — a schema pattern for dynamic attributes where each attribute is stored as a row rather than a column.
SKU Stock Keeping Unit — a unique code identifying a product in the catalog.
UUID v7 A time-sortable universally unique identifier. Recommended as primary key for all entities.

License

MIT License. Pattern concepts based on "Enterprise Patterns and MDA" by Jim Arlow & Ila Neustadt (Addison-Wesley, 2003).