~learn.

Visa/Mastercard Global Payment Network, the whole design.

A card network that routes ~434B authorizations a year between merchants' banks and ~14,500 card-issuing banks in a sliver of a 2-second checkout, moving messages in real time and money later in netted batches.

7 diagrams · 8 sections · revise in ~10 min · Download PDF prints it in the light theme, diagrams included

SQ-04 · Visa/Mastercard Global Payment Network · design sheethimanshukukreja.in/learn/sheets/bonus-04-visa-mastercard-payments

At a glance#

Number Value What it drives
Transactions ~434B / year (2025, both networks) ~1.19B a day · ~13,800 TPS average
Peak ~55,000 TPS (4× on Black Friday) build for ~100,000; VisaNet tested at 65,000+ msg/s
Latency < 2 s end to end · < 200 ms network tiered issuer timeouts, ~1 s in all
Fraud scoring < 1 ms · 500+ attributes features in memory, no network calls
Issuers ~14,500 banks (Visa) BIN table in RAM, per-issuer stand-in rules
Message ~600 B encrypted ISO 8583 ~1 Gbps per data centre at 100K TPS
Storage ~3.5 KB / txn → ~4.2 TB / day ~32 PB with 7-year retention and 3× replication
Availability 99.9999 % (~32 s a year) multi-DC, stand-in, never double-charge

Architecture#

DiagramThe network on one page: acquirer → switch → issuer, money settles later
%% title: The network on one page: acquirer → switch → issuer, money settles later
flowchart TD
  POS@{ icon: "sd:card", label: "POS terminal · online checkout<br/>175M+ merchant locations" } --> ACQ@{ icon: "sd:bank", label: "Acquirer + processor<br/>merchant's bank · builds ISO 8583" }
  ACQ ==>|"leased lines · MPLS VPN"| MG["Message gateway<br/>parse ISO 8583 · decrypt fields · idempotency"]:::edge
  MG ==> RS["Authorization switch<br/>BIN lookup in RAM · WAL · tiered timeouts"]:::hot
  RS --> FD["Fraud scorer<br/>500+ attributes · < 1 ms · score 0–99"]:::core
  FD --> RD@{ icon: "tech:redis", label: "Redis Cluster<br/>per-card velocity · sharded by PAN hash" }
  RS ==>|"request + risk score"| ISS@{ icon: "sd:bank", label: "Issuer gateway + core banking<br/>approves or declines" }
  ISS -.->|"no answer in budget"| SIP["Stand-in processing<br/>issuer's rules · queued to reconcile"]:::service
  RS --> KF@{ icon: "tech:kafka", label: "Kafka<br/>transaction events" }
  KF --> PG@{ icon: "tech:postgresql", label: "PostgreSQL<br/>authorization records" }
  PG -->|"clearing files matched to auths"| CLR["Clearing + settlement<br/>interchange · net positions"]:::service
  CLR -.->|"T+1 to T+2"| SET@{ icon: "sd:building", label: "Banks settle net positions<br/>Fedwire · SWIFT" }
  class POS client
  class ACQ,ISS external
  class RD cache
  class KF queue
  class PG,SET store
DiagramInside the switch: one ID, an overlapped WAL, tiered timeouts
%% title: Inside the switch: one ID, an overlapped WAL, tiered timeouts
flowchart TD
  REQ["Auth request<br/>acquirer ID + txn ID"]:::edge --> ID{"Seen this key<br/>in the last 24 h?"}
  ID -->|"yes"| CACHED["Return the stored response<br/>no second charge"]:::ok
  ID -->|"no"| WORK["WAL append starts, overlapped<br/>BIN < 1 μs · fraud score < 1 ms"]:::core
  WORK --> T1["Primary issuer endpoint · 500 ms"]:::service
  T1 -->|"timeout"| T2["Backup endpoint · 300 ms"]:::service
  T2 -->|"timeout"| T3["Stand-in · 200 ms<br/>e.g. ≤ $500 · ≤ $2,000 a day · score ≤ 80 · not lost or stolen"]:::queue
  T1 -->|"answer"| RESP["Respond after the WAL commit<br/>cache it under the key"]:::ok
  T2 -->|"answer"| RESP
  T3 --> RESP

Key flows#

DiagramAuthorization: tap to approval in under 2 s
%% title: Authorization: tap to approval in under 2 s
sequenceDiagram
  autonumber
  participant P as POS terminal
  participant A as Acquirer
  participant N as Network switch
  participant I as Issuer
  P->>A: card data · amount · ISO 8583
  A->>N: auth request · acquirer ID + txn ID
  Note over N: idempotency check · BIN → issuer · WAL append starts
  N->>N: fraud score in under 1 ms
  N->>I: request + risk score
  I->>I: check limit and own fraud rules
  I-->>N: approve · auth code
  N-->>A: approve (after WAL commit)
  A-->>P: approved · receipt
  Note over P,I: no money has moved · network share under 200 ms
DiagramIssuer silent, then the acquirer retries
%% title: Issuer silent, then the acquirer retries
sequenceDiagram
  autonumber
  participant A as Acquirer
  participant N as Network switch
  participant I as Issuer
  A->>N: auth request (txn T1)
  N->>I: primary endpoint
  I--xN: no answer in 500 ms
  N->>I: backup endpoint
  I--xN: no answer in 300 ms
  N->>N: stand-in on issuer rules (200 ms)
  alt within limits, score ok, card not flagged
    N-->>A: approved by stand-in
  else outside the rules
    N-->>A: declined
  end
  Note over N,I: stand-in decision queued · issuer reconciles and owns it
  A->>N: retry T1 after its own timeout
  N-->>A: same stored response · no second charge
DiagramClearing and settlement: T+0 to T+2
%% title: Clearing and settlement: T+0 to T+2
sequenceDiagram
  autonumber
  participant M as Merchant
  participant A as Acquirer
  participant N as Network
  participant I as Issuer
  M->>A: end of day · batch of the day's sales
  A->>N: clearing file
  N->>N: match each record to its auth · interchange · net per bank
  alt amount differs from auth (tip, fuel, hotel)
    N->>N: accept within tolerance · over it, notify issuer
  end
  N->>A: settlement file · net credit
  N->>I: settlement file · net debit
  I->>N: one net transfer (Fedwire or SWIFT)
  N->>A: one net transfer
  A->>M: merchant credited, less fees
  Note over M,I: e.g. $100 sale: issuer $2.00 · network $0.20 · acquirer $0.30 · merchant $97.50

Data model#

DiagramCore entities
%% title: Core entities
classDiagram
  class Authorization {
    +txnId : string
    +acquirerId : string · with txnId, idempotency key
    +panHash : string
    +amount : minor units
    +currency : ISO code
    +mcc : 4 digits
    +responseCode : 00 / 51 / 59 / 91
    +riskScore : 0–99
    +standIn : bool
  }
  class IssuerRoute {
    +bin : 6–8 digits
    +primaryEndpoint : string
    +backupEndpoint : string
    +timeoutMs : int
    +supportsStandIn : bool
  }
  class StandInRules {
    +singleTxnLimit : money
    +dailyLimit : money
    +maxRiskScore : int
  }
  class Velocity {
    +panHash : string · shard key
    +txns : sorted set by time
    +amounts : sorted set by time
    +merchants : sorted set by time
  }
  class ClearingRecord {
    +txnId : string
    +authCode : string
    +amount : may differ from auth
    +interchangeFee : money
  }
  class SettlementPosition {
    +bankId : string
    +netAmount : plus receives, minus pays
    +txnCount : int
  }
  Authorization "many" --> "1" IssuerRoute : routed by BIN
  IssuerRoute "1" --> "1" StandInRules : issuer sets
  Authorization "many" --> "1" Velocity : updates
  Authorization "1" --> "0..1" ClearingRecord : cleared as
  SettlementPosition "1" --> "many" ClearingRecord : nets

Lifecycle#

DiagramAuthorization state machine
%% title: Authorization state machine
stateDiagram-v2
  [*] --> RECEIVED
  RECEIVED --> SCORED: new key · fraud score
  RECEIVED --> REPLAYED: key seen · cached answer
  SCORED --> AT_ISSUER: routed by BIN
  AT_ISSUER --> APPROVED: issuer approves
  AT_ISSUER --> DECLINED: issuer declines
  AT_ISSUER --> STAND_IN: primary + backup time out
  STAND_IN --> APPROVED: within issuer rules
  STAND_IN --> DECLINED: outside rules
  APPROVED --> CLEARED: T+1 batch, matched
  CLEARED --> SETTLED: net transfer, T+1 to T+2
  CLEARED --> DISPUTED: chargeback in window
  SETTLED --> [*]
  DECLINED --> [*]
  REPLAYED --> [*]
  DISPUTED --> [*]
  class SETTLED ok
  class DECLINED,DISPUTED bad
  class STAND_IN queue

Decisions#

Decision Chose Over Because
Network's role Route messages; banks hold money Holding funds no funds at risk; scales as a router
Moving money Batch clearing, net settlement T+1/T+2 Transfer per swipe one net transfer per bank, not millions
Issuer unreachable Stand-in on issuer rules Decline, or wait shopper gets an answer; risk stays bounded
Retries Key = acquirer ID + original txn ID, 24 h cache Resend to issuer never double-charge
Durability WAL overlapped; response waits for it Write first, or after replying no answered auth lost, no added latency
Replication Sync to regional peer, async across regions Sync everywhere fits the budget; WAL catches peers up
Fraud features In-memory velocity, one pipelined read DB query per auth under 1 ms

When it breaks#

Failure What users see Contain it with
Issuer slow on Black Friday an answer within ~1 s stand-in for that issuer, reconcile later
Acquirer retries after a timeout one charge cached response under the idempotency key
Data centre outage a blip route to the backup DC, failover < 30 s (target)
Redis velocity cluster fails payments continue fall back to conservative limits
Fraud model overruns 1 ms no delay proceed on rules
Card-testing botnet across merchants honest shoppers unaffected count per BIN, merchant, device; 3-D Secure on affected card-not-present BINs; tell issuers

Say it in the interview#