Skip to main content

Decision Rules

TL;DR
  • This page is an index, not a textbook. Every row is a one-line rule plus a link to the page that owns the argument. If a rule surprises you, follow the link.
  • Pick by the constraint that bites first: who the client is, what the call shape is, where the state lives, and what a failure costs.
  • Most of these are tradeoffs, not winners. HTTP/3 does not retire HTTP/2, L7 does not retire L4, and a NAT gateway does not retire the free gateway endpoint.
  • Defaults worth saying aloud: dual-stack for IPv6, SG as the application filter with a NACL as backstop, externalized session state over sticky sessions, versioned URLs over cache purges.

Cheat sheet​

Transport and HTTP​

OptionStrengthCostPick whenOwner
TCPIn-order, reliable, flow- and congestion-controlled byte streamHandshake; one lost segment stalls everything behind it; no message boundariesYou need every byte, in order, and can wait for retransmissionTransport overview
UDPOne sendto is one datagram; no setup; you own the semanticsNo promises: loss, duplication and reordering are your problem; spoofable sources make it an amplification weaponLate is worse than lost, or you are building your own transport (QUIC, WireGuard, DNS retries)UDP
QUICReliability, TLS 1.3 and independent streams in one user-space transport over UDP; 1 RTT handshakeNeeds a UDP path, so browsers keep a TCP fallbackLossy, mobile or high-RTT paths where HTTP/3 pays offQUIC and HTTP/3
HTTP/1.1Simple; persistent connectionsOne request in flight per connection (browsers open about six per host)Simple or legacy clientsHTTP/1.1 and HTTP/2
HTTP/2Many streams multiplexed on one connection; HPACK header compressionOne lost TCP segment stalls every streamDefault over TLS when TCP is fineHTTP/1.1 and HTTP/2
HTTP/3HTTP over QUIC; a lost packet stalls only the streams it carriedNeeds UDP; gains are small on a fast wired pathMobile, lossy or high-RTT usersQUIC and HTTP/3

API style and real-time​

OptionStrengthCostPick whenOwner
RESTPlain HTTP; caches, proxies and browsers understand itNo built-in streamingPublic APIs, CRUD, anything that must work with caches and browsersRPC and APIs
gRPCRequired .proto schema, binary protobuf, all four call shapesBrowsers need gRPC-Web or Connect; an L4 balancer pins one client to one backendService to service, streaming, many languagesRPC and APIs
GraphQLClient names exactly the fields it wantsNot cacheable by default (queries are POST)Many client types with different data needsRPC and APIs
WebhookProvider calls you when something happensAt-least-once: verify the signature, dedupe by event idBeing told that something happenedRPC and APIs
PollingOrdinary requests, best proxy friendlinessStaleness up to the poll intervalDashboards that tolerate staleness, job statusReal-time patterns
Long pollingOrdinary requests, about one one-way delay to see an eventClient re-issues each request; proxies may time out held onesFallback transport, restrictive networksReal-time patterns
SSEServer to client over plain HTTP; automatic reconnect with Last-Event-IDOne-way, UTF-8 text only; a buffering proxy can hold events backNotifications, live feeds, LLM token streamsReal-time patterns
WebSocketFull duplex, text or binaryNeeds proxy Upgrade support; you write reconnect and heartbeatsChat, games, collaborative editingReal-time patterns

Load balancing and traffic steering​

OptionStrengthCostPick whenOwner
L4 load balancerAny TCP or UDP protocol, very high packet rates, can preserve the client IPSees IP and port onlyRaw speed, non-HTTP protocols, fixed IPsLoad balancing
L7 load balancerRoutes on host, path, header or cookie; retries, rewrites, WAFTerminates the client connection; more work per requestRouting depends on the request itselfLoad balancing
DNS-based steeringPicks a region by changing the DNS answerCached and bounded by TTL; coarseSending users to a regionGlobal traffic steering
Round robinTrivialIgnores loadRequests cost about the sameLoad balancing
Least connections or P2CKeeps the busiest backend far less loadedNeeds connection countsRequest costs differLoad balancing
Consistent hashingAdding a node moves only about 1/(N+1) of keys, where hash % N moves N/(N+1)Lumpy load without virtual nodesCache locality or sharded stateConsistent hashing
Sticky sessionsIn-memory session state survives between requestsUneven load; scale-in and failure lose the sessionOnly where affinity is genuinely wantedLoad balancing
Stateless backendsAny backend serves any requestState moves to a shared store or signed tokenThe defaultLoad balancing
Hash on source IP (L4)Needs no cookieMisfires behind NAT, where many users share one addressL4 affinity with no other handleLoad balancing
Cookie affinity (L7)Pins per browser, not per addressL7 onlyL7 affinityLoad balancing
Single-site unicastOne address, one placeOne site is the failure domainOne region is enoughGlobal traffic steering
Anycast-fronted multi-siteOne IP announced from every site; routing picksFollows BGP policy, not geography or latency; a route change can move a user mid-connectionMulti-site with fast failoverGlobal traffic steering
Active-activeSmall RTOA hard data problem (writes, replication lag, fencing)You can solve multi-writer dataGlobal traffic steering
Active-passiveSimplicityA failover eventOne writer region is acceptableGlobal traffic steering

TLS, proxies and crypto​

OptionStrengthCostPick whenOwner
Terminate TLS at the LBOne place for certificates; L7 can read and route; backends skip handshake CPUThe LB-to-backend leg is plaintext unless re-encryptedMost web servicesLoad balancing
Terminate and re-encryptSame, plus an encrypted backend legA second encrypted hop to runCompliance requires itLoad balancing
PassthroughEnd-to-end encryption; routing only on SNILB cannot read requests; every backend holds the certificateEncrypted bytes must stay opaque to the LBLoad balancing
Forward proxyActs for clients: egress control, filteringSame shape as a reverse proxy, opposite sideControlling outbound trafficProxies and gateways
Reverse proxyActs for servers: ingress, hides backendsBackend sees the proxy's IP unless passed onFronting serversProxies and gateways
Symmetric cryptoFast bulk encryption (AEAD)Needs a shared key firstCarrying the dataSymmetric crypto and hashing
Asymmetric cryptoKey agreement and signatures with no pre-shared secretSlower; not used for bulk dataEstablishing trust and a keyKey exchange and public-key crypto
Hybrid (what TLS does)Public-key crypto bootstraps; a symmetric cipher carries the dataBoth mechanisms to get rightAlways, in practiceTLS

Cloud networking​

OptionStrengthCostPick whenOwner
Security groupStateful, allow-only, on the interface; replies return automaticallyNo deny rulesThe application's filterSecurity groups vs NACLs
NACLStateless, numbered, allow and deny, at the subnet edgeRules for both directions, including ephemeral return portsA coarse backstop, or the way to write an explicit deny, which security groups cannotSecurity groups vs NACLs
VPC peeringPoint-to-point route wiringNon-transitive; ranges must not overlap; full mesh needs n(n-1)/2 peeringsA few VPCsPrivate connectivity
Transit gatewayHub: one attachment per VPC; transit worksBilled per attachment-hour and per GB processedMany VPCsPrivate connectivity
PrivateLink (interface endpoint)Exposes one service, one way; works with overlapping CIDRsNot a network; billed per hour and per GBOverlapping CIDRs or one-service exposurePrivate service endpoints
Site-to-site VPNIPsec over the internet; up in minutesPer-tunnel bandwidth ceilingFast start, or backup for a dedicated linkPrivate connectivity
Dedicated link (Direct Connect, Interconnect, ExpressRoute)Steady latency, high bandwidthPhysical cross-connect, plan in weeksPrimary hybrid pathPrivate connectivity
NAT gatewayManaged many-to-one outbound IPv4Billed per hour and per GB; SNAT port limitsPrivate subnets reaching the internetNAT gateways and egress
NAT instanceSame behaviour, you control the boxYou patch, size and make it highly available; a single point of failureRarely; the managed gateway replaced itNAT gateways and egress
Gateway endpoint (S3, DynamoDB)A route-table entry; freeOnly those two servicesReaching S3 or DynamoDB from private subnetsPrivate service endpoints
VPN (WireGuard or IPsec)Encrypted path across an untrusted networkCosts MTU, so clamp the MSS; moves trust to the VPN operatorJoining sites or remote usersVPN, IPsec and WireGuard

Caching, DNS and resilience​

OptionStrengthCostPick whenOwner
Straight to originNothing to configureEvery user pays the full round trip; origin takes every requestSmall, local audienceCDN
CDN in frontShorter round trips and a shielded originInvalidation and cache-poisoning risksAnything with distant users or load to absorbCDN
Pull CDNFetches on a miss; change only DNS and headersFirst user per PoP pays a missMost sites and APIsCDN
Push CDNNo cold miss; origin off the pathStorage you pay for; upload and invalidation logic you ownLarge, rarely changing, predictable filesCDN
Versioned URLs (content hash)Long lifetimes with exact invalidationNeeds a build stepAssetsHTTP caching
Short or revalidated lifetimeChanges reach users quicklyMore requestsThe HTML that points to the assetsHTTP caching
Short DNS TTLA changed record reaches clients quicklyMore walks, more load on authoritative serversBefore a planned changeDNS resolution
Long DNS TTLCheaper and faster on averageA bad record stays wrong for up to the TTLStable recordsDNS resolution
New connection per requestSimplestTCP plus TLS 1.3 is 2 RTTs before the request is answered; ports pile up in TIME_WAITRarelyTCP performance
Keep-alive and poolingPays the handshake onceIdle connections can be dropped by NATs and balancersAlmost alwaysTCP performance
RetrySurvives transient failureCan duplicate work and sustain overloadIdempotent calls or calls with an idempotency key, with backoff, jitter and a budgetTimeouts, retries and backoff
Fail fastProtects the callerThe user sees the errorNon-idempotent work, or a failing dependency (circuit breaker)Timeouts, retries and backoff

Layer 2, routing and addressing​

OptionStrengthCostPick whenOwner
HubRepeats bits to every portOne shared collision domainLegacy gear onlySwitches and MAC learning
SwitchForwards only toward the destination MAC; each port is its own collision domainOne broadcast domain unless splitConnecting hosts on a LANSwitches and MAC learning
RouterJoins broadcast domains; cross-VLAN traffic goes through itPer-hop forwarding decisionJoining networksVLANs
VLANSplits a switch into separate broadcast domainsTraffic between VLANs must cross a routerSegmenting a LANVLANs
SubnetThe IP-layer prefix a router forwards onNeeds addressing and routingPlanning address spaceSubnet design practice
OSPFLink-state: every router holds the same map and runs Dijkstra; fast, consistent convergenceScope is one ASRouting inside one organizationOSPF
BGPExchanges reachability between ASes; path chosen by policyNot shortest path: Local Preference is checked before AS-PATH lengthRouting between organizationsBGP
Dual-stackWorks with IPv6 and IPv4-only peersTwo stacks to run and secureThe defaultIPv6
IPv6-onlyNo NAT neededNeeds NAT64/DNS64 to reach IPv4-only servicesA deliberate choice, not a defaultIPv6

Textbook vs real world​

The textbook saysProduction doesWhy
Use REST outside and gRPC insidePick by client and call shapeIt is a habit, not a law (RPC and APIs)
HTTP/2 is strictly better than HTTP/1.1It can lose on a lossy linkOne lost segment stalls every stream on the single connection (HTTP/1.1 and HTTP/2)
Anycast sends you to the nearest siteIt sends you where BGP policy saysPolicy, not geography or latency (Global traffic steering)
Use sticky sessions to keep users logged inExternalize session stateStickiness breaks on scale-in, deploys and failure, and skews load (Load balancing)
New design means IPv6Dual-stack, with IPv6-only as a deliberate choiceThe real transition path is dual-stack plus Happy Eyeballs (IPv6)

Gotchas​

GOTCHAS3
Greenfield means IPv6 only
Unicast versus anycast is a tradeoff
Use UDP when occasional loss is acceptable

Interview questions​

INTERVIEWREST versus gRPC: when would you pick each?mid
Show answer

Pick by who the client is and what the call looks like. REST fits public APIs and CRUD because caches, proxies and browsers understand plain HTTP. gRPC fits service to service and streaming: a required .proto schema, binary protobuf over HTTP/2, and all four call shapes. Browsers need gRPC-Web or Connect, and an L4 balancer pins one client to one backend, so use an L7 proxy or client-side balancing. Row detail: RPC and APIs.

Follow-ups:

  • Where does GraphQL fit? Many client types with different data needs, at the cost of default HTTP caching.
  • Does gRPC set a deadline? No, so you must set one.
INTERVIEWPolling, WebSocket or SSE for a live feed?mid
Show answer

Start with direction. If only the server pushes (notifications, live feeds, token streams), SSE is plain HTTP with built-in reconnect and Last-Event-ID resume. If both sides talk freely (chat, games), WebSocket gives full duplex but needs proxies to handle Upgrade and you write reconnect and heartbeats. Polling is for dashboards that tolerate staleness, and long polling is a fallback on restrictive networks. See Real-time patterns.

Follow-ups:

  • What kills an idle connection? NATs and load balancers; AWS ALB defaults to 60 s, so send an application heartbeat well under that.
  • How should clients reconnect? Exponential backoff plus jitter.
INTERVIEWL4 versus L7 load balancing: what are the tradeoffs?senior
Show answer

L4 sees IP and port only, so it is fast and protocol-agnostic and can preserve the client IP, but cannot route on content. L7 terminates the client connection and opens its own to the backend, so it can route on host, path, header or cookie, retry, rewrite, and terminate TLS, at more cost per request. With TLS passthrough the balancer is effectively L4 and can only route on SNI. See Load balancing.

Follow-ups:

  • Why does gRPC need care? An L4 balancer pins all of one client's calls to one backend.
  • How does the backend see the client IP behind L7? X-Forwarded-For or the PROXY protocol.
INTERVIEWHow do you choose between a push and a pull CDN?senior
Show answer

Pull is the default: the CDN fetches from the origin on a miss, so you change only DNS and headers, but the first user per PoP pays a miss. Push has you upload ahead of time, which suits large, rarely changing, predictable files where the origin should be off the path, at the cost of storage and invalidation logic you own. See CDN.

Follow-ups:

  • What about purging? Prefer versioned URLs, then purge by tag; a CDN purge does not touch browsers (HTTP caching).
  • How do you protect the origin? Accept traffic only from the CDN so the origin cannot be bypassed.