Skip to content

Resiliency

Baseline resiliency is inherited from the Base Template. Entitlements-specific considerations:

Catalog reconciliation

ProductCatalogReactionStateMachine reacts to ProductRetiredEvent to close assignments referencing a retired product. Because the saga can replay events, ReactToCatalogProductRetiredAsync must be idempotent - closing already-closed assignments should be a no-op.

Per-tenant invariant

UQ_Entitlements_TenantId guarantees a single entitlement aggregate per tenant; CreateDraftAsync throws EntitlementAlreadyExistsForTenantException on a second draft. Edition assignment requires an active entitlement (EditionAssignmentRequiresActiveEntitlementException).

Write serialization

EntitlementEditorGrain (keyed by tenant id) serializes concurrent writes per tenant.

See also