- Use single-case discriminated unions to create distinct types for domain primitives: `type CustomerId = CustomerId of int` prevents mixing IDs.
- Model state machines with discriminated unions: each case represents a valid state and carries only the data relevant to that state.
- Use `private` constructors with `create` smart constructors returning `Result` to enforce invariants on domain types.
- Prefer records with `{ record with field = newValue }` update syntax for modeling immutable value objects and aggregates.