Real-time vs batch processing for loyalty points calculation

Our loyalty program processes about 500K transactions daily and we’re debating architectural approaches for points calculation. Currently running batch jobs every 30 minutes but considering moving to real-time event-driven processing.

The main driver is customer experience - members want to see points reflected immediately after purchase, especially for mobile app users. Our current 30-minute delay generates support calls and complaints. However, I’m concerned about eventual consistency issues and system load from processing events in real-time.

We’re also looking at caching strategies since many calculations involve complex tier multipliers and promotional rules. Batch processing allows us to reconcile discrepancies easily, but real-time makes that harder. Has anyone dealt with provisional points calculations where you show estimated points immediately then reconcile later?

Would appreciate insights on event-driven architecture patterns that work well for loyalty calculations at scale.

Real-Time vs Batch for Loyalty Points Calculation at Scale

Both approaches are viable at 500K daily transactions (~6 TPS average, with likely 10–20× peak spikes). The right choice depends on your tolerance for complexity versus latency.


Criteria Comparison

Criteria Batch (30-min) Real-Time Event-Driven Provisional + Reconcile Hybrid
Customer visibility Delayed Immediate Immediate (estimated), confirmed later
Implementation complexity Low High Medium-High
Consistency guarantees Strong (post-run) Eventual Eventual with audit trail
Reconciliation effort Built-in Requires compensation logic Explicit reconciliation job
Throughput scaling Predictable Requires careful backpressure design Mixed
Rule/tier complexity Handles well Requires caching layer Cached for display, exact on reconcile
Support call volume High (your current state) Low Low
Failure recovery Rerun batch Idempotency + dead-letter queues Hybrid retry patterns

Key Architectural Considerations

Event-driven patterns that work at this scale: A Kafka or SAP Event Mesh topology where each POS/checkout transaction fires a transaction.completed event consumed by a points calculation service works well. Idempotency keys on every event are non-negotiable — duplicate events from retries will corrupt balances without them.

The provisional points pattern is the most pragmatic answer to your UX problem without fully committing to real-time consistency. The flow:

  1. On transaction.completed, calculate estimated points using a lightweight rules snapshot (cached tier multipliers, active promotions)
  2. Write provisional balance to a fast read store (Redis or SAP Commerce cache layer)
  3. Expose provisional balance in mobile app with a visual indicator (“Points pending confirmation”)
  4. A downstream reconciliation job (can still be batch, hourly or nightly) runs exact calculation against authoritative rules engine and corrects any delta
  5. Publish points.confirmed event to update the member’s ledger

This isolates the UX improvement from the consistency risk.

Caching strategy for complex rules: Cache your tier multiplier tables and promotional rule snapshots with a TTL aligned to your promotion activation windows — typically 5–15 minutes. Stale cache causing a minor points delta is recoverable; stale cache causing a negative customer experience is not. Flag promotional edge cases (flash promotions, last-minute tier upgrades) as “requires exact calculation” and route those to an async confirmation path rather than provisional.

Eventual consistency handling: Design your points ledger as an append-only event log, not a mutable balance field. Each provisional entry and each correction becomes a ledger row. This makes reconciliation auditable and simplifies debugging discrepancies — verify this pattern is supported in your specific SAP Loyalty Management or custom ledger implementation.

Backpressure at peak: At 20× average TPS during peak, your event consumer needs circuit breakers and queue depth monitoring. A stalled consumer silently falling behind is worse than a transparent batch delay.


The right architecture depends on your reconciliation SLA tolerance, existing SAP CX component versions, and whether your mobile app team can implement provisional UX states — depends on context / your requirements.


This draft is based on general SAP Customer Experience (SAP CX) knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

We migrated from batch to event-driven last year. The key is accepting eventual consistency as a feature, not a bug. We calculate provisional points synchronously on transaction events (usually completes in 80-120ms) and display those immediately to customers. Then asynchronous validators run within 5 minutes to verify against promotional rules, tier qualifications, and fraud checks. If discrepancies occur (happens in about 2% of cases), we adjust and notify the customer. This hybrid approach gives instant gratification while maintaining accuracy.

Event-driven architecture is the right direction but implement circuit breakers and bulkheads. We process 800K daily transactions and learned the hard way that a spike in events can overwhelm downstream services. Use message queues (we use Kafka) to buffer events, implement consumer groups for parallel processing, and set up dead letter queues for failed calculations. Our real-time calculation service handles 95% of cases in under 100ms, with complex scenarios falling back to async processing. Cache frequently accessed tier configurations and promotional rules in Redis with 5-minute TTL to reduce database load.

Batch reconciliation is still critical even with real-time processing. We run nightly batch jobs that compare real-time calculated points against authoritative calculations using complete data. This catches edge cases where events arrived out of order or were processed during rule transitions. The batch job identifies discrepancies and creates adjustment transactions. In three months of production, we’ve found 0.3% discrepancy rate - mostly timing issues around promotional period boundaries. Customers appreciate the transparency when we credit missing points with explanatory messages.

From a mobile app perspective, provisional points display transformed our user engagement. We show points updating in real-time with a small indicator that says ‘pending verification’ for the first 2 minutes, then it becomes solid once async validation completes. Users love seeing immediate feedback. The technical implementation uses WebSocket connections for point updates - when the async validator completes, we push the final confirmed total to connected clients. Conversion rates on our loyalty-driven offers increased 23% after implementing real-time updates.

One aspect often overlooked is operational monitoring. With batch processing, you have clear job completion metrics and error logs. Event-driven systems require distributed tracing to track individual transactions through the calculation pipeline. We implemented correlation IDs that flow through the entire event chain - from purchase event through provisional calculation, async validation, and final reconciliation. This visibility is essential for debugging discrepancies and meeting SLA commitments. Set up alerts for calculation latency exceeding 200ms and validation completion exceeding 5 minutes.

Having implemented both approaches across multiple loyalty programs, here’s my comprehensive analysis of the architectural trade-offs:

Event-Driven Architecture: This is the optimal path forward for customer experience. Implement a multi-stage pipeline: (1) Transaction event triggers immediate provisional calculation, (2) Event published to message queue for async processing, (3) Validation services consume events and verify calculations, (4) Reconciliation service handles discrepancies. Use Apache Kafka or AWS EventBridge for reliable event delivery with guaranteed ordering per customer partition key.

Architectural pattern:


// Pseudocode - Event processing flow:
1. Purchase transaction triggers PointsCalculationEvent
2. Sync handler calculates provisional points (timeout: 150ms)
3. Publish to validation queue with correlation ID
4. Async validators process within 5min SLA
5. Discrepancy handler reconciles differences
// Reference: SAP CX Event-Driven Architecture Guide

Eventual Consistency: Embrace it as a design principle. Display provisional points immediately with visual indicators (“Pending” badge for first 2 minutes). Our testing shows 98.7% of calculations complete validation within 90 seconds with no adjustments needed. For the 1.3% requiring adjustment, send push notifications explaining the change - transparency builds trust. Implement idempotency keys to prevent duplicate point awards if events are replayed.

Caching Strategy: Multi-layer caching is critical for performance. Layer 1: In-memory cache (Caffeine) for tier configurations and active promotional rules (5-minute TTL). Layer 2: Redis for customer tier status and recent transaction history (15-minute TTL). Layer 3: Database read replicas for complex rule evaluations. This caching reduces database queries by 85% and enables sub-100ms provisional calculations. Invalidate caches proactively when rules change rather than relying solely on TTL.

Batch Reconciliation: Don’t eliminate batch processing - evolve it. Run nightly reconciliation comparing event-driven calculations against authoritative batch calculations. This catches edge cases: out-of-order events, partial failures, rule transition timing issues. Our reconciliation identifies 0.2-0.4% discrepancy rate, automatically creates adjustment transactions, and generates customer notifications. The batch job also validates that all transactions have corresponding point awards - catching any events lost in the pipeline.

Provisional Points Calculation: Implement a two-tier calculation model. Tier 1 (synchronous, 80-150ms): Calculate base points using cached rules, apply standard tier multipliers, check for obvious promotional matches. Return provisional total to customer immediately. Tier 2 (asynchronous, 1-5 minutes): Validate against all active promotions, check for tier threshold crossings, verify fraud rules, apply complex stacking logic. If Tier 2 differs from Tier 1, create adjustment transaction and notify customer.

For your 500K daily volume, provision for 3x peak capacity (1.5M daily). Use consumer groups with 5-10 parallel workers per calculation stage. Implement exponential backoff for retries (max 3 attempts) and dead letter queues for systematic failures requiring manual review. Monitor queue depth - alert if backlog exceeds 1000 events or oldest event exceeds 30 seconds age.

Migration strategy: Run parallel systems for 30 days. Process all transactions through both batch and event-driven pipelines, compare results, tune the event-driven system until discrepancy rate drops below 0.5%. Then cut over mobile apps to real-time display while maintaining batch as reconciliation safety net. This phased approach minimizes risk while delivering immediate customer experience improvements.