vishal maurya

HLD Fundamentals for Beginners: Estimation, Building Blocks and a Payments Lens

Overview

Part of the Interview Prep series. Dotted-underline words are glossary terms: hover for the meaning or open the Glossary. Track your progress on the Interview Prep tracker. Series index: Start here.

1. HLD vs LLD in one minute

HLD (high-level design) answers "which boxes exist and how do they talk": load balancer, services, database, cache, queue. LLD (low-level design) answers "what classes and methods are inside one box". The same interview can have both; payments companies often ask LLD for coding and HLD for a senior discussion.

2. The 6-step framework (use it every time)

  1. Requirements: functional (what it does) and non-functional (scale, latency, availability, consistency). Ask about users, peak traffic, read vs write ratio.
  2. Estimation: QPS, storage, bandwidth (see section 3).
  3. API and data model: the 3-5 main endpoints and the main tables.
  4. High-level diagram: client, CDN, load balancer, services, cache, DB, queue.
  5. Deep dive: pick the 1-2 hardest parts (hot keys, consistency, idempotency) and go deep.
  6. Bottlenecks and trade-offs: what breaks at 10x? single points of failure? monitoring?

3. Back-of-envelope estimation (the QPS cheat sheet)

Memorise: 1 day = 86,400 seconds, about 10^5. So:

  • 1 million requests per day is about 10 requests per second (QPS).
  • 100 million per day is about 1,200 QPS average.
  • Peak is usually 3x to 10x the average. Payments peak much higher on sale days.

Worked example: "a payment gateway handling 50 million transactions a day".

average TPS   = 50,000,000 / 86,400 = about 580
peak TPS      = 580 x 5 = about 2,900 (design for ~3,000, test at 2x)
record size   = 1 KB per payment (id, amounts, status, attempts, timestamps)
storage / day = 50M x 1 KB = 50 GB/day; 1 year = about 18 TB (plus indexes, replicas x3 => ~55 TB)
bandwidth     = 3,000 TPS x 1 KB = 3 MB/s (tiny; the hard part is correctness, not bytes)

Latency numbers worth remembering: memory read 100 ns, SSD read 100 microseconds, network inside a data centre 0.5 ms, cross-region 100+ ms, a disk database query 1-10 ms.

4. The building blocks

4.1 DNS, CDN, load balancer

  • DNS turns names into IP addresses. CDN serves static files from servers near the user.
  • A load balancer spreads requests over many servers and removes unhealthy ones.
L4 load balancerL7 load balancer
Works onIP address and TCP/UDP portFull HTTP request: path, headers, cookies
Can route by URL or header?NoYes (/pay to the payment service, /search to search)
Can terminate TLS, rewrite, compress?Usually noYes
SpeedFaster, less CPUSlightly slower, smarter
ExamplesAWS NLB, HAProxy (TCP mode)AWS ALB, Nginx, Envoy
Use whenraw throughput, non-HTTP protocols, put in front of L7microservice routing, canary, auth, rate limits

The "L" means a layer of the OSI networking model (L4 = transport/TCP, L7 = application/HTTP). A common production setup is L4 in front, L7 behind.

An API gateway is an L7 front door adding authentication, rate limiting and routing.

4.2 Caching

Cache = small fast memory for hot data. Patterns: cache-aside (app reads cache, on miss reads DB and fills cache), write-through (write both), write-back (write cache, flush later; risky). Always decide TTL and eviction (LRU is the default). Beware cache stampede: a hot key expires and thousands of requests hit the DB; fix with locks, jittered TTL, or serving stale. Never cache balances as the source of truth.

4.3 Databases

  • SQL (relational): transactions (ACID), joins, strong consistency. Default choice for money.
  • NoSQL: key-value (Redis, DynamoDB), document (MongoDB), wide-column (Cassandra), graph. Choose for huge scale, flexible schema, simple access patterns.
  • Indexes make reads fast, writes slower.
  • Replication: leader accepts writes, followers serve reads; beware replication lag (stale reads).
  • Sharding: split data by a key (user id, merchant id) across databases. Pick a key that spreads load; avoid hot keys. Consistent hashing reduces data movement when adding nodes.

4.4 CAP and consistency

During a network partition you choose consistency (refuse to answer rather than be wrong) or availability (answer, maybe stale). Money movement chooses consistency. Feeds, likes and recommendations choose availability (eventual consistency).

4.5 Queues and streams

A message queue (Kafka, RabbitMQ, SQS) decouples producers from consumers, absorbs spikes and lets you retry. Delivery is usually at-least-once, so consumers must be idempotent. Use a dead-letter queue for poison messages and the outbox pattern to publish events reliably.

4.6 Rate limiting, idempotency, reliability

  • Rate limiting: token bucket / sliding window per user or API key, enforced at the gateway (see the Rate Limiter LLD post).
  • Idempotency key: the client sends a unique key; the server stores the first result and replays it on retries. Mandatory for payments.
  • Retries with exponential backoff and jitter, only for safe errors. Circuit breaker to stop hammering a failing dependency. Bulkheads to isolate resource pools. Timeouts everywhere.
  • Saga instead of distributed transactions across services, with compensating actions (refund, reversal).

4.7 Observability and operations

Three signals: logs, metrics (QPS, error rate, p99 latency), traces. Define SLIs (what you measure) and SLOs (the target, for example 99.95% of payments under 2 seconds). Deploy safely with canary or blue-green releases.

4.8 Security (payments)

TLS everywhere, never store CVV, tokenise card numbers, encrypt PAN, HMAC-sign webhooks, keep PINs inside an HSM, audit logs, least privilege (PCI-DSS).

5. How a payment actually flows

CARD
 Customer -> Merchant site -> Payment gateway (PSP) -> Acquirer bank -> Card network (Visa/Mastercard/RuPay) -> Issuer bank
                                   |  <------------------ approve / decline travels back ------------------------|
                                   +-> webhook to merchant, ledger entries, settlement next day (T+1/T+2)

UPI
 Customer app (PSP app) -> NPCI UPI switch -> Remitter (payer) bank debit -> NPCI -> Beneficiary bank credit
                                   |  result is often ASYNC: PENDING first, final status by callback or status check

Key ideas to say out loud: authorisation then capture then settlement; idempotency at every hop; reconciliation against bank files; double-entry ledger; PENDING states and callbacks; retry vs failover rules (never retry a decline; never blind-retry a timeout).

6. Worked HLD skeleton: a payment gateway

 Merchant --HTTPS--> [L7 LB / API gateway: auth, rate limit, idempotency check]
                         |
                    [Payment service]  --> [Routing service] --> Bank connectors (HDFC, ICICI, NPCI)
                      |       |                                    (circuit breaker, retries)
                      |       +--> [Ledger service] --> SQL (double-entry, sharded by merchant)
                      +--> [Kafka: payment-events] --> Webhook workers (retry + DLQ) --> Merchant
                                                    --> Notification, Fraud, Analytics
          Redis: idempotency keys (TTL), rate limits      Reconciliation job <- bank settlement files

Deep-dive talking points: payment state machine, idempotent writes (DB unique key), outbox for events, sharding by merchant id with hot-merchant handling, active-active regions with a single writer per payment, reconciliation.

7. Classic HLD questions (all in the tracker)

URL shortener, rate limiter, notification service, payment gateway, wallet and UPI, news feed, chat, ride matching, e-commerce checkout, distributed cache, search autocomplete. The tracker lists them in an order that reuses building blocks, so each design feels like "the last one plus one new idea".

8. Common mistakes

  • Skipping estimation, or doing it without stating assumptions.
  • Drawing boxes without saying why (every box needs a reason: scale, availability or isolation).
  • Using NoSQL for money without discussing transactions.
  • No idempotency, no retry story, no monitoring.
  • Not discussing failures: what happens when the bank is down, the queue is full, a node dies?
  • Ending without trade-offs and the "what breaks at 10x" discussion.