juspay / juspay/decision-engine

Sticky routing: Redis storage layer — per-customer net habit counts

Open
#413 0 comments 0 reactions 1 assignee Claimed by @prajjwalkumar17 View on GitHub
Dominant language
Rust
Stars
128
Forks
36
Avg merge
1d 15h
Merged PRs (30d)
34

Description

Part of #393 (sticky routing). **Status: implemented** in #419 (commit `575d249`), pending review/merge.

One Redis hash per `(merchant, customer)` holds the customer's NET habit counts — successes add one, gateway failures subtract one (floored at zero; failures never create a key or field, and only positive counts qualify as pin candidates):

```
Key: sticky_gw_{merchant_id}_{customer_id} (ids trimmed, case preserved)
Field: {PM}:{PMT}:{connector} (PM/PMT case-folded, connector verbatim)
Value: integer net count (+1 success, -1 failure, floor 0) (HINCRBY — atomic under concurrent feedback)
```

Example: `sticky_gw_m1_cust42` → `{ "INTERAC:RTP:GIGADAT": 3, "INTERAC:RTP:LOONIO": 2 }`. Listpack-encoded: **136 B** for a typical 2-combo customer, **952 B** at the 30-combo cap (measured on Redis 7.2.7) — ~150–250 MB per 1M active customers.

Eviction safety (sticky keys must never crowd out SR/elimination state):
1. **Sliding TTL** on every hash, re-armed in the same MULTI as the write (`STICKY_ROUTING_KEY_TTL`, default 90 days). Idle customers self-evict; every key stays volatile.
2. **Per-customer combo cap** (`STICKY_ROUTING_MAX_COMBOS_PER_CUSTOMER`, default 30): a new field over the cap prunes the lowest-count fields (full excess drains), keeping the hash listpack-encoded.
3. **Per-merchant admission budget** (`STICKY_ROUTING_MAX_CUSTOMERS_{mid}`, default 1M new hashes per TTL window, tracked by two-window counters `sticky_gw_adm_{mid}_{window}` with TTL 2×window): once spent, existing customers keep updating but no new keys are created — growth bounded up front, no reliance on Redis eviction.

New wrapper commands on `RedisConnectionWrapper`: `hincrby_with_expire` (MULTI: HINCRBY+EXPIRE so a hash can never exist without a TTL), `hgetall_map`, `hdel_field`. Module: `src/sticky_routing.rs`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.