Cascading at Provider Level
1) What is cascading and why is it in iGaming
Provider cascading - dynamic selection and/or sequential switching between several PSP/acquirers for the same payment attempt or for traffic distribution in general. Objectives:- AR↑/ DR↓: bypassing "capricious" issuers, choosing the best PSP for a specific BIN/geo/method.
- Cost of ↓: IC + +/markup lower on the part of the basket, minimizing the fix on the micro-ticket.
- Resilience: failover in incidents, degradation of 3DS, falling payment corridors.
- Compliance: compliance with geopolitics, sanctions, local bans and licenses.
2) Cascading patterns
1. Sequential
PSP_A → (soft-decline/tekhnichesky refusal) → PSP_B → PSP_C.
A "narrow window" of retrays is used so as not to create duplicates/risks of multiple holding of funds.
2. Parallel (split-traffic/multi-arm)
Flow distribution (%/rule) between multiple PSPs for benchmark, rule learning, and correlated failure reduction.
3. Sticky BIN / Sticky GEO
Memorizing the "best" PSP for a specific BIN/issuer/geo (decision caches with TTL).
4. Method-aware / Feature-aware
Different providers for cards, A2A, wallets, local methods; taking into account the specifics of 3DS-rails, DCC/FX behavior, tokenization.
5. Limit-aware / SLA-aware
Accounting for provider limits, reserves, SLA incidents, cut-off and funding delays.
3) Rules-engine: inputs
Card features: BIN/IIN, brand, debit/credit, commercial/premium, country of issuer.
Geo and compliance: player's country (IP/GPS/SIM/KYC), sanctions, licenses.
Transaction: amount (minor units), currency, channel (web/app), risk rate.
History of providers: AR/DR by BIN/geo/method for the last 15-60 minutes, soft-decline share, 3DS-pass-rate.
Cost: IC + +/markup/fix, FX spread, rolling reserve%.
Restrictions: rate-limit provider, maintenance/incidents, caps of daily turnover.
Output: priority list of routes' [(PSP, MID, require_3DS, retry_window_ms, max_attempts)] '.
4) Retreats, idempotence and safety
Idempotency-key per attempt (user_id+order_id+nonce) common to all providers in the cascade.
Retray only on soft-decline (network/3DS/timeout/insufficient funds), never with "hard" codes (stolen, do not honor again, etc.).
Anti-duling: 'AUTHORIZED '/' CAPTURED' status closes cascade; all other branches are cancelled.
Windows: 1st retray ≤ 2-5 seconds, total budget ≤ 15-30 seconds, including UX.
3DS policy: possible step-up on the second/third branch if the first fell without 3DS.
5) 3DS, liability shift и AR
The choice of'frictionless '/' challenge' depends on the risk and PSP support (delegated auth, TRA, whitelisting).
In "hard" geo/issuers - forced 3DS on part of the basket.
Track liability shift by providers: where it is more often achieved - transfer risky BINs there.
6) Cost: IC++, blended, fix and FX
For each PSP, consider effective take-rate = interchange + scheme + markup + fixed + FX-slippage.
In the cascade, use the price function in scoring the route:- `Score = w1AR_live + w2(−Cost_bps) + w3(SLA_health) + w4(FX_quality) +...`
- Micro-ticket: the weight of the fix is higher → providers with a low fix are preferable.
- Separately, consider reserve% and funding T + N - affects the cache flow.
7) Incidents, cut-off and routing
Health feed: PSP/corridor statuses (auth API, 3DS ACS, payout rails).
Auto-failover: instant reroute when AR/health falls below threshold.
Cut-off-aware: Before closing a settlement, avoid partial-capture on a PSP with an awkward T + N.
Throttling: in order not to "burn out" the provider's limit, post traffic.
8) Minimal data model
sql
-- Providers and MIDs
CREATE TABLE ref. providers (
provider TEXT PRIMARY KEY, model TEXT, pricing_model TEXT, fx_policy TEXT, reserve_pct NUMERIC, meta JSONB
);
CREATE TABLE ref. mids (
mid TEXT PRIMARY KEY, provider TEXT REFERENCES ref. providers, country TEXT, method TEXT, descriptor TEXT, meta JSONB
);
-- Cascade Rules/Profiles
CREATE TABLE ref. cascade_profiles (
profile_id BIGSERIAL PRIMARY KEY, name TEXT, version TEXT, enabled BOOLEAN, meta JSONB
);
CREATE TABLE ref. cascade_rules (
rule_id BIGSERIAL PRIMARY KEY, profile_id BIGINT REFERENCES ref. cascade_profiles,
geo TEXT, bin_from TEXT, bin_to TEXT, method TEXT,
provider TEXT, mid TEXT, require_3ds BOOLEAN, priority INT,
retry_on_soft JSONB, max_attempts INT, ttl_seconds INT, enabled BOOLEAN, meta JSONB
);
-- Online Provider Performance Metrics (Sliding Window)
CREATE TABLE live. provider_stats_15m (
provider TEXT, method TEXT, geo TEXT, bin6 TEXT,
approvals INT, declines INT, soft_declines INT, three_ds_pass INT,
avg_latency_ms INT, updated_at TIMESTAMP
);
-- Transactions with idempotency and selected route
CREATE TABLE payments. auth_attempts (
attempt_id BIGSERIAL PRIMARY KEY, idempotency_key TEXT, step INT,
provider TEXT, mid TEXT, require_3ds BOOLEAN, status TEXT, decline_code TEXT,
amount_minor BIGINT, currency TEXT, bin TEXT, geo TEXT,
started_at TIMESTAMP, finished_at TIMESTAMP, meta JSONB
);
9) SQL analysis templates
9. 1. Online provider rating (AR and soft-decline share)
sql
SELECT provider, method, geo,
SUM(approvals) AS appr,
SUM(declines) AS decl,
ROUND(100. 0 SUM(approvals) / NULLIF(SUM(approvals+declines),0), 2) AS ar_pct,
ROUND(100. 0 SUM(soft_declines) / NULLIF(SUM(declines),0), 2) AS soft_share_pct
FROM live. provider_stats_15m
WHERE updated_at > now() - INTERVAL '20 minutes'
GROUP BY 1,2,3
ORDER BY ar_pct DESC, soft_share_pct DESC;
9. 2. Cascade effect on orders (step-conversion)
sql
WITH s AS (
SELECT idempotency_key,
MAX(step) AS steps,
BOOL_OR(status='APPROVED') AS approved
FROM payments. auth_attempts
WHERE started_at BETWEEN:from AND:to
GROUP BY 1
)
SELECT steps,
COUNT() AS orders,
100. 0 SUM(approved::int) / NULLIF(COUNT(),0) AS conv_pct
FROM s
GROUP BY 1
ORDER BY 1;
9. 3. Sticky BIN: the best BIN6 provider
sql
SELECT bin6,
provider,
ROUND(100. 0 SUM(approved)::NUMERIC / NULLIF(COUNT(),0), 2) AS ar_pct
FROM (
SELECT LEFT(bin,6) AS bin6, provider, (status='APPROVED') AS approved
FROM payments. auth_attempts
WHERE started_at BETWEEN:from AND:to
) t
GROUP BY 1,2
QUALIFY ROW_NUMBER() OVER (PARTITION BY bin6 ORDER BY ar_pct DESC) = 1;
9. 4. All-in take-rate
sql
SELECT provider,
SUM(amount_reporting) AS volume_rep,
SUM(interchange_amt + scheme_amt + markup_amt + auth_amt + refund_amt + cb_amt + gateway_amt + fx_spread_amt) AS fees_rep,
100. 0 SUM(interchange_amt + scheme_amt + markup_amt + auth_amt + refund_amt + cb_amt + gateway_amt + fx_spread_amt)
/ NULLIF(SUM(amount_reporting),0) AS take_rate_pct
FROM finance. settlement_fees
JOIN dw. transactions_flat USING (provider)
WHERE period_start_at >=:from AND period_end_at <:to
GROUP BY 1
ORDER BY take_rate_pct;
10) KPIs and dashboards
AR/DR by provider and BIN/geo/method (online windows 15/60 min and day-to-date).
Step-conversion: share of approvals on the 1st, 2nd, 3rd branch.
Take-Rate% and FX-slippage by provider/MID.
3DS pass-rate and liability shift share.
Health/SLA: latency, timeouts, error rate, incidents.
Reserve & Funding: reserve% and T + N hit-rate by provider.
11) Alerts and thresholds
Routing Degradation: AR drop at selected provider> Y bps in 10-30 minutes.
Soft-decline surge: an increase in the share of soft-decline → allow an additional branch of the cascade.
3DS Anomaly: 3DS pass-rate drop> X% at specific issuer/BIN cluster.
Take-Rate Spike: all-in cost growth> bps threshold.
Health Down: SLA breach (latency/error) — авто-failover.
Policy Drift - attempts without idempotency_key/bez cascade profile - P1.
12) AB tests and rule training
Multi-arm bandit or fixed split-traffic to new routes.
Explore/Exploit: keep part of the traffic to "learn" sticky BIN.
Rating horizons: online (15/60 min) for incidents and week/month for cost.
Guardrails: minimum AR/max take-rate to stop the experiment.
13) Compliance and "extreme" cases
Respect sanctions/licenses/geoblocks: some providers cannot serve individual countries/methods.
Same-method/Return-to-source: The cascade should not break the return policy.
Tokenization/PCI: a single token scheme between PSPs (network tokens/vault).
Chargebacks: log which branch capture passed through - for disputes.
14) Best practices (short)
1. Retract only soft-decline, with a single idempotency_key.
2. Keep live telemetry AR/3DS/soft-decline and health providers.
3. Build the route pricing function (AR vs Cost vs SLA vs FX).
4. Use sticky BIN and AB tests; versioning cascade profiles.
5. Be cut-off-aware: don't produce partial-capture at the end of the day.
6. Have playbooks failover: PSP/ACS/payout corridor drop.
7. Separate data and responsibility: who holds PAN, who leads disputes.
8. Keep reserve-ledger by provider: releases and write-offs.
15) Implementation checklist
- Provider Card/MID, Pricing (IC + +/blended), FX Policies, Reserves, T + N.
- Rules-engine: profiles, rules, soft-codes, 3DS policy, limits.
- Router: idempotency, retrays, timeouts, sticky BIN cache.
- Telemetry: live AR/DR/3DS/latency/health metrics; alerts.
- Incident management and failover playbooks.
- ETL for fees/FX/reserve; take-rate and step-conversion showcases.
- AB test procedures and guardrails.
- Documentation: compliance restrictions, same-method returns, liability.
Summary
Cascading at the provider level is not "try another PSP," but a discipline: live metrics, smart rules-engine, strict idempotence, correct 3DS tactics, accounting for the cost/FX/of reserves and ready-made failover scenarios. This architecture increases AR, reduces all-in take-rate and makes the payment loop resistant to crashes and regulatory restrictions.