After implementing loyalty systems for several global retailers on D365, here’s what actually works in production for distributed point calculations:
Distributed Transactions: Avoid distributed transactions entirely - they don’t scale and create more problems than they solve. Instead, use single-region transactions with asynchronous replication. Each region has authoritative write ownership for its customers’ point transactions. Cross-region redemptions route to home region for the transaction, accepting slightly higher latency for consistency guarantee.
Saga Pattern: Implement saga orchestration for complex point operations. For redemptions involving multiple systems (D365, inventory, payment), create a saga coordinator that manages the workflow. Each step is atomic within its service, with compensating transactions defined upfront. Use Azure Durable Functions for saga orchestration - the state management and retry logic are built-in. Your saga steps would be: 1) Reserve points (with timeout), 2) Validate redemption eligibility, 3) Process reward fulfillment, 4) Commit point deduction, 5) Notify customer. If any step fails, compensating transactions roll back previous steps.
Event Sourcing: This is ideal for loyalty programs. Store every point transaction as immutable event (earned, redeemed, expired, adjusted). Current balance is projection from event stream. Benefits: complete audit trail for compliance, ability to recalculate balances if bugs found, temporal queries for customer history. For event store size concerns, implement snapshots every 100 events per account and archive events older than 2 years to cold storage. We typically see 200-500 events per active customer annually, which is very manageable in Cosmos DB.
Consistency Models: Use different consistency levels based on operation type. For balance queries (read-heavy), use Session consistency with sticky sessions ensuring customers see their own writes. For point accrual (write-heavy, low risk), use Eventual consistency - if there’s 2-second lag showing earned points, customers don’t notice. For point redemptions (write-critical), use Strong consistency to prevent double-spend. Cosmos DB allows per-request consistency level override, so configure this in your data access layer.
Implementation pattern that works: Write all point transactions to home region with Strong consistency. Use change feed to replicate to other regions asynchronously. Balance queries use Session consistency with session token passed in request headers. For redemptions, implement optimistic concurrency with ETag checks and automatic retry on conflict (max 3 retries with exponential backoff). Add circuit breaker that falls back to Strong consistency across all regions if conflict rate exceeds 1% - indicates potential synchronization issue requiring investigation.
This hybrid approach gives you 99.9% of benefits of multi-region writes with none of the consistency headaches. The key insight: not all operations need same consistency level, and accepting slightly higher latency for critical operations is better than dealing with inconsistent state.