Pricing Drift Detection
Overview
Pricing drift detection monitors discrepancies between expected and actual pricing throughout the checkout and order creation process.
What is Pricing Drift?
Pricing drift occurs when:
- Snapshot price doesn't match current pricing
- Payment amount doesn't match snapshot price
- Price lists change during checkout
- Pricing engine version changes
Drift Detection Points
1. Payment Intent Creation
Detects drift between snapshot and payment intent amount:
async detectPaymentIntentDrift(
checkoutId: string,
engineTotal: number,
paymentIntentAmount: number,
snapshot: PricingSnapshot
): Promise<void> {
const tolerance = 0.01; // ₹0.01 tolerance
const difference = Math.abs(engineTotal - paymentIntentAmount);
if (difference > tolerance) {
await auditService.logDrift({
checkoutId,
expected: paymentIntentAmount,
actual: engineTotal,
driftDetails: {
reason: "Engine total does not match payment intent amount",
mismatchType: "PAYMENT_INTENT_AMOUNT_MISMATCH"
},
severity: "CRITICAL"
});
throw new BadRequestException("Pricing drift detected");
}
}
2. Webhook Processing
Detects drift between snapshot and webhook payment amount:
async detectWebhookDrift(
checkoutId: string,
paymentIntentId: string,
snapshot: PricingSnapshot,
webhookPaymentAmount: number
): Promise<void> {
const tolerance = 0.01;
const difference = Math.abs(snapshot.totalEffectivePrice - webhookPaymentAmount);
if (difference > tolerance) {
await auditService.logDrift({
checkoutId,
paymentIntentId,
expected: webhookPaymentAmount,
actual: snapshot.totalEffectivePrice,
driftDetails: {
reason: "Snapshot total does not match webhook payment amount",
mismatchType: "WEBHOOK_PAYMENT_AMOUNT_MISMATCH"
},
severity: "CRITICAL"
});
throw new BadRequestException("Pricing drift detected");
}
}
3. Order Creation
Detects drift in rule hash and engine version:
async detectOrderCreationDrift(
orderId: string,
snapshot: PricingSnapshot,
currentPriceLists: PriceList[]
): Promise<void> {
const currentHash = computePriceListHash(currentPriceLists);
if (snapshot.ruleHash !== currentHash) {
await auditService.logDrift({
orderId,
driftDetails: {
reason: "Price list rules changed between snapshot and order creation",
mismatchType: "RULE_HASH_MISMATCH",
snapshotHash: snapshot.ruleHash,
currentHash
},
severity: "WARNING" // Warning, not critical (price lists may have changed)
});
}
if (snapshot.engineVersion !== PRICING_ENGINE_VERSION) {
await auditService.logDrift({
orderId,
driftDetails: {
reason: "Pricing engine version changed",
mismatchType: "ENGINE_VERSION_MISMATCH",
snapshotVersion: snapshot.engineVersion,
currentVersion: PRICING_ENGINE_VERSION
},
severity: "WARNING"
});
}
}
Drift Severity Levels
CRITICAL
Blocks checkout or order creation:
- Payment amount mismatch
- Snapshot validation failure
- Engine calculation error
WARNING
Logs drift but allows operation:
- Rule hash mismatch (price lists changed)
- Engine version mismatch (engine updated)
- Minor calculation differences
Drift Report
Admin can view drift reports:
GET /admin/pricing/drift-report?dateFrom=2025-12-01&severity=CRITICAL
Response:
{
"data": [
{
"id": "drift-123",
"checkoutId": "checkout-456",
"orderId": "order-789",
"severity": "CRITICAL",
"expected": 1000.00,
"actual": 999.99,
"difference": 0.01,
"driftDetails": {
"reason": "Payment amount mismatch",
"mismatchType": "PAYMENT_INTENT_AMOUNT_MISMATCH"
},
"timestamp": "2025-12-18T10:30:00Z"
}
],
"total": 1,
"page": 1,
"limit": 50
}
Drift Detection Flow
Tolerance
Default tolerance: ₹0.01 (1 paise)
Allows for minor rounding differences while catching significant drift.
Audit Logging
All drift events are logged to pricing_audit_logs table:
CREATE TABLE pricing_audit_logs (
id UUID PRIMARY KEY,
event TEXT NOT NULL,
checkout_id UUID,
order_id UUID,
variant_id UUID,
price_list_id UUID,
customer_group_id UUID,
expected_amount DECIMAL(10,2),
actual_amount DECIMAL(10,2),
drift_details JSONB,
severity TEXT,
timestamp TIMESTAMP NOT NULL
);
Best Practices
- Monitor Regularly: Review drift reports weekly
- Investigate Critical: Investigate all CRITICAL drift events
- Set Alerts: Alert on CRITICAL drift events
- Track Trends: Monitor drift trends over time
- Document Changes: Document price list changes
Common Causes
- Price List Updates: Price lists changed during checkout
- Rounding Errors: Minor rounding differences
- Engine Updates: Pricing engine version changed
- Bundle Changes: Bundle definitions changed
- Concurrent Modifications: Multiple price list updates
Edge Cases
- Zero Tolerance: Some scenarios require zero tolerance
- Negative Drift: Drift can be negative (over-charge)
- Multiple Drifts: Multiple drift types can occur simultaneously
- Missing Snapshot: Handle gracefully if snapshot missing