Network & API Protocols: PE Trade-Off Analysis

Twelve protocols across four layers. The key insight before any table: these do not all compete. TCP and gRPC are not alternatives, they stack. Compare within a layer, choose across layers.

CATEGORY SWEEP / LAYERED

As of 2026-05-22

PE Verdict

Default to TCP + TLS 1.3 + HTTP/2 as the substrate, REST for public APIs, gRPC for internal service-to-service, and SSE for server push. Reach past these only when you can name the inflection point: REST to GraphQL when client-driven over-fetching dominates your latency budget, SSE to WebSocket when the client must push mid-stream, HTTP/2 to HTTP/3 when lossy mobile networks make TCP head-of-line blocking your tail-latency villain, and WebSocket to WebTransport only when you need unreliable datagrams and control UDP egress end to end.

Layer framing: Transport (TCP, UDP) carries bytes. Security (TLS) wraps the transport. App-transport (HTTP/1.1, HTTP/2, HTTPS) frames bytes into messages. API-style (REST, gRPC, GraphQL, WebSocket, SSE, WebRTC) models the actual contract. Matrix tables below are grouped by layer so no comparison forces non-peers into the same columns.

The Layer Map

Read this first. Most protocol confusion comes from comparing across layers. "REST vs TCP" is a category error.

API STYLE / SEMANTICSREST   gRPC   GraphQL   WebSocket   SSE   WebRTC ← where your real design choices live
APP TRANSPORTHTTP/1.1   HTTP/2   HTTPS (+ HTTP/3) ← frames bytes into requests/messages
SECURITYTLS ← encrypts and authenticates whatever rides on it. HTTPS = HTTP + TLS
TRANSPORTTCP   UDP ← move bytes host to host

gRPC runs over HTTP/2. GraphQL and REST usually run over HTTP. HTTP/3 runs over QUIC, which runs over UDP. WebRTC and WebTransport ride UDP. Everything reliable ultimately rides TCP unless it deliberately opts into UDP.

Best default choices

1. Trade-Offs

One table per protocol. A trade-off is giving up X to get Y. Click a header to sort. Grouped by layer.

Transport TCP & UDP

TCP

Use as the reliable byte-stream substrate when ordered delivery, congestion control, and broad middlebox compatibility matter more than loss-tolerant latency.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
In-order reliable deliveryBytes arrive intact and ordered, no app-level reassemblyLatency floor from retransmit + ack cyclesLossy mobile/satellite links where one drop stalls everything queued behind itThis is head-of-line blocking. It is the single reason HTTP/3 abandoned TCP.
Connection-orientedStateful flow control and congestion control for free3-way handshake adds a full RTT before first byteShort-lived connections at high churn, handshake cost dominates payloadConnection reuse (keep-alive) amortizes this. Cold connections to far regions hurt most.
Congestion control built inFair sharing, backs off under loss automaticallyThroughput collapses on the classic loss-equals-congestion assumptionWireless loss that is not congestion still triggers backoff, tanking throughputBBR vs CUBIC matters here. Wireless loss fooling CUBIC is a real on-call latency mystery.
Kernel-implementedBattle-tested, ubiquitous, hardware-offloadedProtocol changes need OS upgrades, not app deploysYou want a transport fix but are pinned to the fleet's kernel versionQUIC moved to user space precisely to escape this upgrade-cycle trap.
Byte stream abstractionSimple mental model, no message framing to manageNo message boundaries, app must frameYou assume one send equals one recv, then two messages coalesceEvery junior bug of "my message got split" is this. TCP is a pipe, not a packet.
Single ordered streamTrivial ordering guaranteesCannot multiplex independent streams without HoL couplingHTTP/2 multiplexes logically but one lost packet blocks all streamsThe reason HTTP/2's multiplexing promise breaks under packet loss.
Mature middlebox supportFirewalls, NATs, LBs all understand TCPOssification, middleboxes mangle anything non-standardRolling a custom transport, middleboxes silently break itProtocol ossification is why QUIC encrypts almost everything, to hide from meddling middleboxes.

UDP

Use when latency and message independence matter more than delivery guarantees, or when a higher-level protocol such as QUIC or WebRTC owns reliability.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
No handshakeZero setup RTT, send immediatelyNo connection state, no built-in security contextYou need auth/encryption and now must build a handshake anywayQUIC adds back a 1-RTT (or 0-RTT) handshake on UDP, proving you usually need it.
No reliability guaranteeNo retransmit stalls, lost data is just goneApp must detect and handle loss itselfYou assumed delivery, packets vanish silently on congested linksCorrect for live media (stale frame is worthless). Wrong for anything that must arrive.
No orderingNo HoL blocking, each datagram independentApp must reorder or tolerate disorderSequence-sensitive logic without sequence numbersThis independence is exactly what QUIC exploits for per-stream delivery.
Datagram boundaries preservedOne send equals one recv, clean message framingCapped at MTU (~1500B) before fragmentationPayloads over MTU fragment, and a single fragment loss drops the whole datagramOpposite of TCP's framing problem. Keep datagrams under path MTU to avoid fragmentation.
Stateless, low overheadMassive fan-out (DNS, multicast), tiny per-packet costNo flow/congestion control, can swamp the networkUnthrottled UDP becomes a self-inflicted DDoS or amplification vectorUDP amplification is a top reflection-attack primitive. Rate-limit and validate source.
Firewall-blocked on many networksN/A — this is purely a costUDP/443 blocked on many corporate and hotel networksWebTransport/HTTP-3 handshake fails fast, must fall back to TCPThe real reason QUIC-based protocols always need a TCP fallback path in production.
Thin protocol surfaceTotal control to build exactly the transport you wantYou reimplement everything TCP gave you for freeHand-rolled reliability has subtle bugs TCP solved decades agoReach for QUIC before hand-rolling reliable UDP. That mistake has been made enough times.

Security TLS

TLS (1.2 / 1.3)

Use by default anywhere confidentiality, integrity, server identity, or mTLS-based workload identity matter; treat certificate automation as part of the system.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
Encryption + integrityConfidentiality and tamper detection on the wireCPU for crypto, though AES-NI makes it cheapVery high connection churn without session resumptionAt scale, terminate TLS at the edge/LB, not every microservice, unless you need mTLS internally.
Handshake cost1-RTT in TLS 1.3, down from 2-RTT in 1.2Still an RTT (or zero with 0-RTT resumption)Cold connections to distant regions, handshake dominates a small requestTLS 1.3 0-RTT replays are a real risk for non-idempotent requests. Gate it.
Server authenticationClient verifies server identity via cert chainPKI operational burden, cert rotation and expiryA cert expires unnoticed and takes down a service at 3amExpired-cert outages are among the most common self-inflicted SEVs. Automate rotation (ACME).
Mutual TLS (mTLS)Both sides authenticated, the zero-trust mesh backboneCert distribution and rotation for every workloadManual mTLS cert management across hundreds of servicesThis is why service meshes (Istio, Linkerd) exist, to automate mTLS you would never hand-manage.
Forward secrecyPast traffic stays safe even if long-term key leaksEphemeral key exchange per session, slight costN/A — mandatory and cheap in TLS 1.3, no reason to skipTLS 1.3 removed all non-forward-secret cipher suites. Good riddance.
Cipher/version negotiationInteroperability across old and new clientsDowngrade-attack surface, weak-cipher footgunsLeaving TLS 1.0/1.1 or RC4 enabled for "compatibility"Pin to TLS 1.2+ minimum, prefer 1.3. Audit cipher suites, do not trust defaults.
Opaque to middleboxesPrivacy, middleboxes cannot read payloadsLoss of network-level inspection and debuggingYou need to debug a payload issue but everything is encrypted on the wireDrives demand for app-level tracing. You cannot tcpdump your way out of a TLS payload bug.

App Transport HTTP/1.1, HTTP/2 & HTTPS

HTTP/1.1

Use as the universal compatibility floor for public APIs and simple request/response systems where debugging and reach matter most.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
Text-based protocolHuman-readable, trivial to debug with curl/telnetVerbose, no header compression, parsing overheadHigh-volume APIs where repeated headers waste bandwidthThe debuggability is real value. It is why REST-over-HTTP/1.1 still dominates public APIs.
One request per connection at a timeDead simple request/response modelApp-level head-of-line blocking within a connectionMany small assets, browser opens 6 parallel connections per origin to compensateThe 6-connection-per-origin hack is the whole reason HTTP/2 multiplexing was invented.
Pipelining (rarely used)Multiple requests without waiting, in theoryResponses still ordered, broken middlebox supportYou enable it and a proxy mangles the response orderEffectively dead. Everyone disabled it. HTTP/2 multiplexing replaced the intent.
StatelessAny server can handle any request, easy horizontal scaleRe-send context (cookies, auth) every requestLarge repeated headers on every call add up at volumeStatelessness is REST's superpower for scaling. The header cost is HTTP/2's HPACK target.
Universal supportWorks literally everywhere, every client and middleboxStuck with 1990s-era inefficienciesN/A — this is the safe-default cost of ubiquityWhen in doubt about reach, HTTP/1.1 is the floor that always works.
Keep-alive connection reuseAmortizes TCP+TLS handshake across requestsIdle connections hold server resourcesConnection pool exhaustion under high concurrencyTune keep-alive timeouts and pool sizes. Default pools are often wrong for your traffic shape.
Chunked transfer encodingStream a response of unknown lengthNo true server push, client must poll or long-pollReal-time needs force long-polling hacksSSE is built on this exact mechanism, a never-closing chunked HTTP response.

HTTP/2

Use when multiplexing, header compression, gRPC support, and fewer connections improve internal or client-facing API efficiency.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
Stream multiplexingMany concurrent requests on one connection, no app HoLAll streams share one TCP connection's fateOne lost packet stalls every multiplexed stream (transport HoL)The multiplexing is real but TCP undermines it under loss. HTTP/3 is the fix.
Binary framingCompact, fast to parse, enables multiplexingNot human-readable, needs tooling to inspectDebugging without proper tools, raw bytes are opaqueThis binary base is what gRPC builds on. You cannot do gRPC on HTTP/1.1 framing.
HPACK header compressionRepeated headers cost almost nothing after first requestCompression state is a shared-connection attack surfaceN/A in practice — HPACK was hardened after CRIME/HEADER attacksThe win is huge for chatty APIs with fat repeated auth headers.
Server pushServer preemptively sends resources client will needPushes waste bandwidth if client already cached themCache-blind push re-sends assets the client already hasSo problematic that Chrome removed support. Treat server push as effectively deprecated.
Single TCP connectionFewer handshakes, less server connection overheadTransport HoL blocking, plus one connection failure kills all streamsLossy mobile networks, the shared connection becomes a single point of stallName the inflection: if your p99 tail is loss-driven on mobile, this is your villain.
Stream prioritizationHint which streams matter mostComplex, inconsistently implemented across serversYou rely on priorities that your server stack ignoresThe HTTP/2 priority tree was so messy HTTP/3 redesigned it entirely.
Requires TLS in practiceEncryption effectively mandatory, ALPN negotiates cleanlyNo realistic plaintext HTTP/2 in browsersTrying to run h2c (cleartext) and finding browsers refuse ith2c exists for internal/gRPC use. Browsers will not speak HTTP/2 without TLS.

HTTPS (HTTP over TLS)

Use for all public web and API traffic; the real design question is where TLS terminates and whether internal hops need re-encryption or mTLS.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
HTTP + TLS compositionEncryption and identity with zero changes to HTTP semanticsInherits all of TLS's handshake and PKI costsCert expiry, handshake RTT, all TLS footguns now apply to your web trafficHTTPS is not a separate protocol. It is HTTP riding TLS. Understanding that demystifies it.
Browser/SEO mandateRequired for HTTP/2, modern APIs, and search rankingNo realistic plaintext option for public webN/A — plaintext HTTP is effectively dead for public sitesLet's Encrypt + ACME made the cost near zero. There is no excuse left for plaintext.
Mixed-content blockingBrowser refuses insecure subresources on a secure pageOne http:// asset can break a https:// pageMigrating a legacy site, a hardcoded http image breaks the padlockAudit every subresource on migration. Mixed-content is the classic HTTPS-cutover gotcha.
HSTS enforcementForces HTTPS, blocks downgrade and SSL-strip attacksA misconfig can lock users out for the max-age windowYou set a long HSTS max-age then need to serve plain HTTP, too lateStart with a short max-age, ramp up. The preload list is essentially permanent, be sure.
Edge TLS terminationOffload crypto to the LB/CDN, simplify backendsPlaintext on the internal hop unless you re-encryptAssuming end-to-end encryption when TLS stops at the edgeKnow where TLS terminates. "It's HTTPS" does not mean encrypted all the way to the pod.
SNI exposureMany certs/hosts on one IP via SNIHostname leaks in cleartext during handshakePrivacy or censorship contexts where the SNI reveals the destinationEncrypted Client Hello (ECH) closes this, but rollout is partial. Know your threat model.
Cert as identityThe cert is the trust anchor for the whole sessionCompromised or mis-issued cert undermines everythingA CA mis-issues, or a private key leaksCertificate Transparency logs and CAA records are your monitoring. Use them.

API Style: Request/Response REST, gRPC & GraphQL

REST

Default for public resource APIs, CRUD workflows, cacheable reads, and broad client compatibility.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
Resource-oriented + HTTP verbsIntuitive, maps to CRUD, leverages HTTP caching/status codesAwkward fit for actions that are not resourcesRPC-style operations (sendEmail, recalculate) jammed into REST nounsThe "everything is a resource" model strains for verbs. That friction is gRPC's opening.
Stateless + cacheableHTTP caching, CDNs, intermediaries all just workCache invalidation complexity, repeated context per requestHighly dynamic data where caching gives little benefitCacheability is REST's most underrated edge over gRPC and GraphQL. Do not throw it away lightly.
Over/under-fetchingSimple, predictable endpointsFixed payloads, clients get too much or too littleMobile clients dragging huge payloads for one field, or N+1 round tripsThis exact pain is what GraphQL was built to solve. Name it before reaching for GraphQL.
JSON payloadsUniversal, readable, schemaless flexibilityVerbose, no enforced contract, parse costHigh-throughput internal calls where JSON bloat and parse cost dominateThe lack of an enforced schema is freedom for public APIs, chaos for internal microservices.
Loose contractEasy to evolve, add fields without breaking clientsNo compile-time safety, drift between client and serverA field rename ships and silently breaks downstream consumersOpenAPI/JSON-Schema bolts on the rigor gRPC has by default. Use it or pay later.
Ubiquitous toolingEvery language, every client, browsers nativelyNo native streaming, polling for real-timeReal-time features force long-polling or a separate WebSocket/SSE channelREST is the control plane. Pair it with SSE/WebSocket for the data plane when you need push.
Human-debuggablecurl, Postman, browser devtools, all trivialVerbosity is the price of readabilityN/A — debuggability usually wins for public-facing APIsNever underrate this. The team velocity cost of opaque protocols is real and recurring.

gRPC

Best inside service meshes and typed service-to-service boundaries where protobuf contracts, deadlines, streaming, and binary efficiency justify the tooling cost.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
Protobuf binary contractCompact payloads, strong typed schema, codegen in every languageNot human-readable, schema-compile step in the buildQuick debugging without grpcurl, raw frames are opaqueThe enforced contract is the whole point for internal meshes. It catches drift at compile time.
HTTP/2 nativeMultiplexed streams, bidirectional streaming, low latencyHard dependency on HTTP/2 features browsers cannot reachCalling gRPC directly from a browser, it simply cannotBrowsers cannot control HTTP/2 frames or read trailers from JS. This is gRPC-Web's reason to exist.
Browser support gapN/A — this is purely a costNeeds gRPC-Web + a proxy (Envoy), and even then no client/bidi streamingYou want browser-to-backend gRPC with full streaming, blocked as of early 2026True bidi streaming needs Fetch duplex, still unshipped in stable browsers in early 2026. Connect-RPC is the pragmatic escape.
Four call types incl. streamingUnary, server-stream, client-stream, bidi, all first-classStreaming semantics add real complexity (backpressure, errors)Treating a long-lived stream like a request, mishandling half-close and flow controlgRPC bidi streaming over HTTP/2 is genuinely powerful server-to-server. Most teams underuse it.
Status in trailersCan stream N records then report final success/failureTrailers are inaccessible to browser FetchBrowser clients cannot read the gRPC status, a core gRPC-Web limitationThis single design choice is why browsers fundamentally cannot speak native gRPC.
Deadlines + cancellationFirst-class deadline propagation across the call chainYou must set and propagate them or lose the benefitNo deadlines set, a slow dependency cascades into resource exhaustionDeadline propagation is a top reason gRPC shines in deep service graphs. REST has no equivalent default.
Tight coupling to schemaGenerated clients, no hand-written HTTP plumbingProto changes ripple to all consumers, governance neededA breaking proto change without field-number discipline breaks everyoneNever reuse or renumber proto fields. The wire format is positional, not name-based.

GraphQL

Use when varied clients need different projections over the same graph and you are prepared to own query cost, caching, and resolver complexity.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
Client-specified queriesClient asks for exactly the fields it needs, no over/under-fetchQuery complexity moves to the server, unpredictable loadA nested query explodes into thousands of resolver callsQuery cost analysis and depth limiting are mandatory, not optional. Unbounded GraphQL is a DoS vector.
Single endpoint + schemaOne graph aggregates many backends, strong introspectable typesHTTP caching mostly breaks, everything is POST to /graphqlYou lose CDN/HTTP caching that REST got for freeYou rebuild caching at the field level (persisted queries, APQ, DataLoader). Real engineering cost.
Resolver modelDecouples schema from data sources, federate cleanlyN+1 query problem is the default failure modeEach field hits the DB separately without batchingDataLoader (batch + cache per request) is not optional. It is the first thing every GraphQL backend needs.
Strong type systemSchema is the contract, great tooling and introspectionSchema design and governance overhead across teamsFederated schema with conflicting ownership and namingFederation (Apollo, etc.) is powerful but the org coordination cost is the real tax.
Mobile/varied-client fitOne API serves wildly different client data needsOverkill for simple, uniform CRUDA 3-endpoint service wrapped in GraphQL machinery for no gainIf your clients all want the same shape, GraphQL is pure overhead. Use REST.
IntrospectionSelf-documenting, powerful dev tooling (GraphiQL)Exposes your whole schema to attackers if left onIntrospection enabled in prod hands attackers a full API mapDisable introspection in prod or gate it. Common security oversight.
Error semanticsPartial results, per-field errorsAlways HTTP 200, errors buried in the bodyMonitoring keyed on HTTP status sees 200 while queries failYour observability must parse the errors array, not trust status codes. Trips up every new team.

API Style: Streaming / Real-Time WebSocket, SSE & WebRTC

WebSocket

Use for bidirectional realtime sessions where both client and server send mid-stream and you can own connection state, replay, and backpressure.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
Full-duplex persistentBoth sides push anytime, low per-message overheadStateful connection, must track and scale themMillions of idle connections pin server memory and FDsConnection count, not message rate, is the scaling wall. Plan for sticky routing and connection budgets.
Starts as HTTP upgradeTraverses firewalls/proxies on 80/443, near-universal supportUpgrade can be blocked or stripped by some proxiesCorporate proxy refuses the Upgrade header, connection fails99%+ browser support since 2015. The reliable real-time default for a reason.
Raw byte/message pipeTotal freedom over message format and protocolNo built-in structure, you build everything (auth, reconnect, heartbeats)Hand-rolled reconnect/heartbeat logic that is subtly brokenYou reinvent a lot. Libraries (Socket.IO) exist precisely because raw WS leaves so much to you.
No auto-reconnectN/A — this is purely a cost vs SSEClient must implement reconnect + backoff itselfNetwork blip drops the socket and nothing reconnectsSSE gives you auto-reconnect free. With WS you own it. A frequent source of "it just stopped" bugs.
Stateful = hard to scaleCheap once connected, no per-message handshakeLoad balancing and horizontal scale get complexScaling out means cross-node message routing (pub/sub backplane)You need Redis/Kafka fan-out to broadcast across server instances. The hidden cost of WS at scale.
Bypasses HTTP semanticsNo per-message HTTP overheadLoses HTTP caching, status codes, standard observabilityYour HTTP-based monitoring and tooling go blind on WS trafficOnce you upgrade, you leave the HTTP ecosystem. Budget for separate observability.
One TCP connectionOrdered reliable delivery for freeSubject to TCP head-of-line blockingLossy network stalls all messages behind a dropped packetThis TCP HoL limitation is exactly what WebTransport-over-QUIC was designed to escape.

SSE (Server-Sent Events)

Use for one-way server-to-client browser streams such as LLM output, notifications, and live dashboards where writes remain normal HTTP requests.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
One-way server pushDead simple, plain HTTP, perfect for token/event streamsServer-to-client only, client cannot push on the same channelYou need the client to send mid-stream, SSE cannotThe inflection: SSE until the client must push, then WebSocket. This is the cleanest boundary in the whole list.
Built on plain HTTPWorks through proxies/firewalls/CDNs, no upgrade danceInherits HTTP/1.1's 6-connection-per-origin limitSeveral SSE streams on HTTP/1.1 exhaust the per-origin connection budgetRun SSE over HTTP/2 to multiplex and dodge the 6-connection cap. A real and common gotcha.
Auto-reconnect built inBrowser EventSource reconnects automatically with Last-Event-IDReconnect/resume semantics are basicComplex resume logic beyond simple last-event replayThe free reconnect + event-ID resume is SSE's quiet superpower over raw WebSocket.
Text-only (UTF-8)Simple line-based wire format, trivial to produceNo binary frames, base64 to ship bytes (~33% bloat)Streaming binary data forces wasteful encodingFor LLM token streaming (text), this is a non-issue and SSE is near-perfect. For binary, look elsewhere.
Native browser EventSourceNo library needed, standardized APIEventSource cannot set custom headers (e.g. auth)Bearer-token auth on SSE needs query params or a fetch-based polyfillAuth-header limitation is the most common SSE surprise. fetch-based SSE clients work around it.
HTTP-native scalingScales with your existing HTTP/LB stackStill a long-lived connection holding a server resourceMany concurrent streams tie up worker threads/connectionsLighter than WebSocket per connection but not free. Async/event-loop servers handle it best.
Unidirectional simplicityNothing to negotiate, no protocol upgradeA control channel needs a separate REST call backYou bolt on REST for client-to-server, now two mechanismsREST (control) + SSE (stream) is a clean, proven pairing. It is exactly the LLM-chat pattern.

WebRTC

Use for peer/media paths, calls, data channels, and low-latency UDP-like delivery where NAT traversal and SFU/TURN planning are part of the product.

Trade-OffWhat You GainWhat You Give UpWhen It Bites YouPE Nuance
Peer-to-peerDirect client-to-client path, lowest latency, server offloadedNAT traversal is hard, needs STUN/TURN infrastructureSymmetric NATs force TURN relay, killing the P2P bandwidth savingsYou still run servers (STUN/TURN). "Serverless P2P" is a myth at scale. Budget for TURN egress.
Built for mediaNative audio/video codecs, jitter buffers, echo cancelEnormous, complex stack for anything non-mediaUsing WebRTC just for a data channel, paying the whole media taxIf you only need data, WebTransport or WebSocket is far simpler. WebRTC's value is media.
UDP-based (SRTP/DTLS)Low latency, drops stale frames instead of stallingUDP blocked on restrictive networks, forced to TCP relayCorporate firewall blocks UDP, calls degrade to slow TURN-over-TCPSame UDP-egress problem as WebTransport. Always have a relay fallback.
Mandatory encryptionDTLS/SRTP always on, no plaintext optionNo way to disable even for debuggingHard to inspect media on the wire for diagnosticsSecurity by default is good. Just know your debugging is at the endpoints, not the wire.
Data channelsConfigurable reliable or unreliable, ordered or not, P2PHeavy signaling + ICE setup before any data flowsShort-lived data needs, setup cost dwarfs the payloadThe flexibility (choose reliability per channel) is great, but only worth it if you are already in WebRTC for media.
Signaling not includedYou choose the signaling channel (WS, etc.)You must build session setup yourselfAssuming WebRTC handles connection setup, it does notWebRTC handles media; you bring the signaling (usually WebSocket). A common architectural surprise.
Mesh scaling limitsDirect paths are ideal for small groupsFull-mesh explodes at O(n^2) connectionsGroup calls past ~4-6 peers melt client uplinksPast a handful of peers you need an SFU (selective forwarding unit). Pure mesh does not scale.

2. Use Cases

Five+ real scenarios per protocol. Driving property is specific, not "scalable". Click to sort.

TCP

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
Database connectionsPostgres, MySQL wire protocolsZero tolerance for lost or reordered bytesThousands of pooled connections per DBUDP would corrupt query/result framing
File transferSFTP, S3 multipart uploadsEvery byte must arrive intact and orderedMulti-GB objectsUDP needs reliability rebuilt anyway
Web traffic (HTTP/1.1, /2)Essentially all of REST and the webReliable ordered request/responseInternet-scaleHTTP/3 uses UDP, but only after rebuilding TCP guarantees in QUIC
Email transportSMTP, IMAPMessage integrity over reliabilityBillions of messages/dayLoss would silently drop mail
Service-to-service RPCgRPC over HTTP/2Ordered multiplexed streamsInternal mesh, 100K+ RPSNeeds the reliable substrate gRPC assumes

UDP

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
DNS lookupsEvery resolver on earthOne-shot query/response, retry is cheapTrillions of queries/dayTCP handshake would triple DNS latency
Live video/audioWebRTC calls, game voiceStale frame is worthless, drop beats stallReal-time, ms-sensitiveTCP retransmit stalls would freeze the call
Online gamingFPS position updatesLatest state matters, old packets are noise60+ updates/sec/playerTCP ordering would replay stale positions
QUIC / HTTP/3Cloudflare, Google edgePer-stream delivery, no transport HoLLarge fraction of modern webTCP cannot give independent stream delivery
Telemetry / metricsStatsD, syslogHigh volume, occasional loss tolerableMillions of datapoints/secTCP overhead unjustified for fire-and-forget

TLS

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
Public web (HTTPS)Every modern websiteConfidentiality + server identityInternet-scalePlaintext is blocked by browsers and SEO
Service mesh mTLSIstio, LinkerdMutual auth in zero-trust networksHundreds to thousands of servicesNetwork-level trust does not survive a breach
API authenticationAny token-based APIProtect bearer tokens in transitAll API trafficTokens in plaintext are trivially stolen
VPN / tunnelsOpenVPN, WireGuard-adjacentEncrypt arbitrary traffic over hostile networksOrg-wideUnencrypted tunnels defeat the purpose
Compliance (PCI, HIPAA)Payments, healthcareEncryption in transit mandated by regulationRegulated workloadsNon-compliance is a legal/financial risk

HTTP/1.1

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
Simple REST APIsMost public APIsUniversal reach, trivial debuggingBroad client diversityHTTP/2 gains marginal for low-concurrency calls
WebhooksStripe, GitHub callbacksOne-shot POST any server understandsMillions of eventsNo need for multiplexing on single calls
Health checksLB / k8s probesDead-simple request, max compatibilityConstant low-volume pollingHTTP/2 overhead pointless for a 200 OK
Legacy/embedded clientsIoT, old SDKsWorks where HTTP/2 cannotConstrained devicesMany embedded stacks lack HTTP/2
SSE foundationAny SSE streamChunked never-ending responsePer-client streamsSSE rides this exact mechanism

HTTP/2

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
gRPC transportInternal microservice meshesMultiplexed bidirectional streams100K+ RPS internalHTTP/1.1 cannot frame gRPC
Asset-heavy web pagesModern SPAsMany concurrent requests, one connectionDozens of assets/pageHTTP/1.1 needs 6 connections + HoL
API gatewaysEnvoy, gatewaysHPACK header compression at volumeHigh-fanout backendsHTTP/1.1 header bloat at scale
Mobile APIs (good networks)App backendsConnection reuse, lower battery/latencyMillions of devicesHTTP/1.1 wastes RTTs on handshakes
Multiplexed SSEMulti-stream dashboardsDodge the 6-connection-per-origin capMany streams/clientHTTP/1.1 SSE hits connection limit

HTTPS

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
All public webEvery site post-2018Encryption + identity, mandatoryInternet-scalePlaintext HTTP is effectively banned
E-commerce / paymentsCheckout flowsProtect payment data in transitGlobal retailPCI forbids plaintext card data
Authenticated appsAny login-gated appProtect session cookies/tokensAll user trafficSession hijacking trivial over HTTP
API endpointsPublic + partner APIsConfidential request/responseAll API callsKeys/tokens exposed in plaintext
HTTP/2 + HTTP/3 enablementPerformance-focused sitesTLS is the prerequisite for bothHigh-traffic sitesBrowsers will not do h2/h3 without TLS

REST

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
Public APIsStripe, Twilio, GitHubUniversal client reach, cacheability, debuggabilityMillions of third-party devsgRPC's browser gap and opacity hurt adoption
CRUD servicesStandard backend resourcesClean verb-to-operation mappingTypical app scaleGraphQL is overkill for uniform shapes
CDN-cacheable contentProduct catalogs, media metadataHTTP caching at the edgeRead-heavy, globalGraphQL POST breaks HTTP caching
Webhooks / integrationsSaaS event deliveryAny HTTP client can receiveMassive partner fan-outgRPC requires special client tooling
Control plane for streamingLLM apps (session/auth/history)Stateless, cacheable, simplePairs with SSE data planeStreaming protocols are wrong for control ops

gRPC

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
Internal microservicesGoogle, Netflix internal RPCTyped contracts, low-latency binary, deadline propagation100K+ RPS, deep call graphsREST/JSON wastes bandwidth and lacks contracts
Polyglot service meshesMixed Go/Java/Python fleetsCodegen from one proto in every languageHundreds of servicesREST means hand-written clients per language
Streaming pipelinesReal-time data servicesBidirectional streaming with backpressureContinuous high-volume streamsREST has no native streaming
Low-latency mobile (good net)Performance-critical app backendsCompact protobuf payloadsMillions of devicesJSON parse + size cost on constrained links
Inter-agent / orchestrator callsAgent platforms (orchestrator to agent svc)Strong contract + streaming for agent resultsMany concurrent agent invocationsREST loses the typed-contract safety net

GraphQL

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
Mobile with varied viewsFacebook (origin), ShopifyEach screen fetches exactly its fields, one round tripMany client versions, slow networksREST over/under-fetches, multiplies round trips
Backend-for-frontend aggregationNetflix, GitHub API v4One graph stitches many microservicesDozens of backing servicesREST forces client-side orchestration
Rapidly evolving frontendsProduct teams iterating fastAdd fields without versioning endpointsFrequent UI changesREST versioning churn slows iteration
Public data graphsGitHub GraphQL APIFlexible client queries over rich schemaLarge third-party dev baseFixed REST endpoints constrain consumers
Federated org-wide schemaLarge eng orgs (Apollo Federation)Teams own subgraphs, unified gatewayMany teams, one graphREST has no native federation story

WebSocket

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
Chat / messagingSlack, DiscordBidirectional, both sides push instantlyMillions of concurrent socketsSSE cannot carry client-to-server messages
Collaborative editingFigma, Google DocsLow-latency two-way state syncMany editors per docPolling/SSE too slow and one-directional
Live trading dashboardsBrokerage platformsPush + client orders on one channelHigh-frequency updatesSSE lacks the client-push path
Multiplayer games (web)Browser gamesReal-time bidirectional statePer-session socketsWebRTC overkill if no media, SSE one-way
Live notifications + actionsInteractive appsServer push plus client acks/actionsPer-user connectionsSSE forces a second REST channel for actions

SSE

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
LLM token streamingChatGPT, Claude-style appsOne-way text stream, HTTP-native, auto-reconnectMany concurrent sessionsWebSocket adds bidirectional complexity you do not need
Live feeds / tickersNews, sports scores, stock pricesServer pushes updates, client only readsBroadcast to many clientsWebSocket is heavier for pure push
NotificationsIn-app alert streamsSimple server-to-client eventsPer-user streamsWebSocket overkill for one-way
Progress / status updatesLong-running job dashboardsStream progress over plain HTTPPer-job streamsPolling wastes requests, WS overcomplicated
Server-driven UI refreshLive dashboards (read-only)Push data changes through proxies/CDNsMany viewersWS upgrade may be blocked by proxies

WebRTC

Use CaseCompany / ScenarioDriving PropertyScale DimensionWhy Not Alternative
Video conferencingGoogle Meet, Zoom webP2P/SFU low-latency media with codecs built inSmall groups to SFU-backed roomsWebSocket has no media stack or NAT traversal
Voice callsDiscord voice, web softphonesUDP media, drop-not-stall, echo cancelPer-call peersTCP-based protocols stall on loss
Screen sharingRemote support toolsReal-time encoded video P2P1:1 or small groupNo other web API ships media handling
P2P file/data transferBrowser file-sharing toolsDirect client-to-client data channel1:1 transfersServer relay adds cost and latency
Cloud gaming / low-latencyGame streaming servicesSub-frame media latency over UDPPer-session streamsOnly WebRTC delivers media-grade latency in-browser

3. Limitations

Severity-rated, with the workaround and what the workaround costs you. Grouped by layer.

Transport + Security

ProtocolLimitationSeverityWorkaroundWorkaround Cost
TCPHead-of-line blocking under packet lossHighMove to QUIC/HTTP-3 (UDP, per-stream delivery)UDP egress issues, newer/less-mature stack
TCPHandshake RTT before first byteMediumConnection keep-alive/pooling, TLS 1.3 0-RTTPool management, 0-RTT replay risk
UDPNo reliability/ordering/congestion controlHighBuild it on top, or use QUICReinventing TCP (badly) or adopting QUIC complexity
UDPBlocked on many corporate/hotel networksHighTCP fallback path always requiredMaintaining two transport paths
TLSCert lifecycle (expiry, rotation)CriticalAutomate with ACME / cert-managerAutomation infra, monitoring, CT log watching
TLS0-RTT replay attacksHighRestrict 0-RTT to idempotent requests onlyRequest classification, careful gating

App Transport

ProtocolLimitationSeverityWorkaroundWorkaround Cost
HTTP/1.1App-level HoL, 6-connection-per-origin capHighUpgrade to HTTP/2 multiplexingTLS requirement, binary debugging
HTTP/1.1No header compression, verboseMediumHTTP/2 HPACKMigration effort
HTTP/2TCP transport HoL undermines multiplexingHighHTTP/3 over QUICUDP egress, operational newness
HTTP/2Server push is cache-blind, deprecatedMediumDo not use it, use preload hintsLose the (questionable) feature entirely
HTTPSMixed-content breaks on migrationMediumAudit and rewrite all subresource URLsMigration audit effort
HTTPSSNI leaks hostname in cleartextMediumEncrypted Client Hello (ECH)Partial rollout, infra support needed

API Style

ProtocolLimitationSeverityWorkaroundWorkaround Cost
RESTOver/under-fetching, N+1 round tripsMediumGraphQL, or BFF aggregation endpointsLose HTTP caching / build BFF layer
RESTNo native streamingMediumPair with SSE or WebSocketSecond protocol/channel to operate
gRPCNo native browser supportCriticalgRPC-Web + Envoy proxy, or Connect-RPCProxy hop, no client/bidi streaming in browser
gRPCOpaque to standard HTTP toolingMediumgrpcurl, server reflection, ConnectSpecialized tooling, learning curve
GraphQLUnbounded query cost (DoS vector)CriticalDepth/complexity limits, persisted queriesQuery analysis infra, allowlist maintenance
GraphQLN+1 resolver problemHighDataLoader batching per requestMandatory extra layer in every backend
GraphQLHTTP caching mostly breaksHighPersisted queries, field-level/CDN cachingRebuild caching you got free in REST
WebSocketStateful, hard to scale horizontallyHighPub/sub backplane (Redis/Kafka), sticky routingBackplane infra, cross-node fan-out cost
WebSocketNo auto-reconnect or HTTP semanticsMediumLibrary (Socket.IO) or hand-rolled logicDependency or bug-prone custom code
SSEOne-way only, no client pushMediumAdd REST for client-to-server, or use WebSocketTwo mechanisms, or heavier protocol
SSEEventSource cannot set auth headersMediumfetch-based SSE client, or token in queryPolyfill, or token-in-URL exposure
WebRTCNAT traversal needs STUN/TURNHighRun STUN/TURN serversInfra cost, TURN relay egress at scale
WebRTCFull-mesh O(n^2) past a few peersHighSFU (selective forwarding unit)Media-server infra and cost

4. Fault Tolerance

Reframed for protocols: how each behaves under failure, recovery, and partition. Matrices grouped by layer so no table exceeds 5 columns. Toggle columns with the chips.

Transport + Security

DimensionTCPUDPTLS
Loss recoveryAutomatic retransmitNone, app's problemInherits transport's
Failure detectionAcks, timeouts, RSTNone nativeHandshake/cert failures surface immediately
Recovery mechanismReconnect + retransmitApp retry logicRenegotiate / new handshake
Connection migrationNo, breaks on IP changeN/A connectionlessNo (QUIC adds this on UDP)
Partition behaviorStalls, then times outSilent dropSession breaks, needs re-handshake
Blast radiusOne connection's streamsSingle datagramOne session
Data loss scenarioOnly on hard reset mid-flightRoutine, by designNone added beyond transport

App Transport

DimensionHTTP/1.1HTTP/2HTTPS
Connection-failure blast radiusOne request (1 of ~6 conns)All streams on that connectionSame as underlying HTTP version
Loss behaviorPer-connection stallTransport HoL stalls all streamsInherits
RecoveryOpen a new connectionReconnect all streams+ TLS re-handshake
Failure isolationGood (independent conns)Poor (shared fate)Matches HTTP version
Retry safetyIdempotency-dependentIdempotency-dependentSame
Cross-region failoverDNS/LB-drivenDNS/LB-driven+ cert must cover failover host
Graceful shutdownConnection closeGOAWAY frame drains streamsSame as HTTP version

API Style

DimensionRESTgRPCGraphQLWebSocketSSE
Retry modelIdempotent verbs safe to retryBuilt-in retry policy + deadlinesPer-query, partial results helpManual reconnect + replayAuto-reconnect + Last-Event-ID
Failure detectionHTTP status codesStatus codes + deadlinesErrors array (HTTP 200!)Heartbeat/ping-pong you buildConnection drop event
Partial failureAll-or-nothing per callAll-or-nothing (stream can partial)Native partial resultsApp-definedResume from last event
Reconnect costNew request, cheapRe-establish streamNew queryFull handshake + state rebuildCheap, automatic
State on reconnectStateless, none lostStream state lostStatelessLost, must resyncEvent-ID resume
Timeout handlingClient/LB timeoutsFirst-class deadline propagationResolver-level timeoutsCustom idle timeoutsHTTP timeouts + reconnect
Cascading-failure guardCircuit breakers (external)Deadlines stop the cascadeQuery timeout + complexity capsBackpressure you implementServer can throttle stream

WebRTC omitted from this matrix: its fault model is media-specific (jitter buffers, packet concealment, ICE restart) and does not map to the request/response dimensions above. In short: it tolerates loss by concealing it, recovers paths via ICE restart, and relies on STUN/TURN for connectivity failures.

5. Connection Scaling & Load Balancing

Protocols do not "shard" like databases. The equivalent concern is how connections distribute across servers and where the scaling wall sits. (This repurposes the skill's Sharding slot, per its edge-case rule for non-applicable dimensions.)

Request/Response Styles

DimensionRESTgRPCGraphQL
LB granularityPer-request (any L7 LB)Per-connection by default, needs L7 for per-callPer-request (single endpoint)
Stickiness needed?No, statelessConnection reuse can pin to one backendNo
Classic balancing pitfallNone majorL4 LB pins long-lived HTTP/2 conns, unbalanced loadOne hot query starves a node
FixStandard round-robinL7 LB or client-side LB (xDS/lookaside)Complexity limits + query routing
Scaling wallBackend throughputConnection distribution skewResolver/backend fan-out cost
Horizontal scale easeTrivial (stateless)Easy, but mind LB layerEasy at edge, hard at resolvers

The gRPC L4-vs-L7 load-balancing trap is a top PE-interview signal: long-lived HTTP/2 connections defeat naive L4 round-robin, so one backend gets hammered. You need L7 (per-request) or client-side balancing.

Streaming Styles

DimensionWebSocketSSEWebRTC
Per-server limitOpen FDs / memory per socketOpen connections (lighter)CPU for media, not connections
Stickiness needed?Yes, connection is statefulYes, long-lived streamSignaling sticky, media P2P/SFU
Cross-node fan-outPub/sub backplane (Redis/Kafka)Same, backplane to broadcastSFU routes media
Scaling wallConcurrent connection countConnection count (higher ceiling)SFU media bandwidth/CPU
Reconnect storm riskHigh (mass reconnect on deploy)High, but auto-reconnect smoothsICE restart, moderate
MitigationJittered backoff, conn drainingJittered reconnectStaggered renegotiation

For all persistent-connection protocols, connection count (not message rate) is the scaling wall, and deploy-time reconnect storms are the classic outage. Jittered backoff and connection draining are mandatory.

6. Message Fan-Out & Delivery Semantics

The protocol analogue of replication: how a message reaches multiple recipients and what delivery guarantee you get. (Repurposes the skill's Replication slot.)

Transport

DimensionTCPUDP
Delivery guaranteeReliable, ordered, exactly-once-ish in-streamBest-effort, may drop/reorder/dup
Multicast/broadcastNo, unicast onlyYes, native multicast/broadcast
Fan-out modelOne connection per recipientOne packet to many (multicast)
OrderingStrict in-orderNone
BackpressureFlow control built inNone, can overrun receiver

API Style

DimensiongRPCWebSocketSSEWebRTC
Native fan-out?No, point-to-point streamsNo, per-connectionNo, per-connectionMesh (small) or SFU
Broadcast mechanismApp + pub/sub backplanePub/sub backplane (Redis/Kafka)Pub/sub backplaneSFU forwards to subscribers
Delivery guaranteeReliable (HTTP/2 + TCP)Reliable (TCP)Reliable + replay via event-IDConfigurable per data channel
OrderingIn-stream orderedOrdered (TCP)OrderedOptional per channel
Replay / resumeApp-definedApp-definedBuilt-in (Last-Event-ID)No (media is ephemeral)
Multi-recipient costN streamsN sockets + backplaneN streams + backplaneSFU CPU/bandwidth

The recurring theme: none of these API-style protocols fan out natively. Real-time broadcast to many clients always means a pub/sub backplane (Redis, Kafka, NATS) behind your connection servers, or an SFU for media. That backplane, not the protocol, is where your delivery guarantees actually live.

7. Better Usage Patterns

Where PE depth shows. What teams get wrong, the better way, and why it compounds.

TCP / UDP

PatternWhat Most Teams Do WrongThe Better WayWhy It Matters
Message framingAssume one TCP send = one recvLength-prefix or delimiter-frame every messageCoalesced/split reads are the #1 raw-socket bug
Congestion control choiceLeave default CUBIC everywhereUse BBR on lossy/long-fat networksCUBIC mistakes wireless loss for congestion, tanking throughput
Connection reuseNew connection per requestPool and keep-aliveHandshake RTT dominates small requests
UDP reliabilityHand-roll acks/retransmit on UDPAdopt QUIC insteadReinventing TCP poorly wastes months and ships bugs
UDP datagram sizeSend payloads over MTUKeep under path MTU (~1200B safe)Fragmentation means one lost fragment drops the whole datagram

TLS / HTTPS

PatternWhat Most Teams Do WrongThe Better WayWhy It Matters
Cert rotationManual renewal, calendar remindersACME automation + expiry alerting + CT monitoringExpired-cert outages are among the most common self-inflicted SEVs
TLS terminationAssume HTTPS means end-to-end encryptedKnow where TLS terminates, re-encrypt internal hops if neededEdge termination leaves plaintext on the internal network
Version/cipher policyTrust defaults, leave old versions onPin TLS 1.2 min, prefer 1.3, audit ciphersDowngrade attacks and weak ciphers are real exposure
0-RTTEnable globally for speedRestrict to idempotent GETs0-RTT replay can double-execute non-idempotent requests
HSTS rolloutSet max long max-age immediatelyRamp max-age, test before preloadA premature long HSTS locks you into HTTPS, hard to undo

HTTP/1.1 & HTTP/2

PatternWhat Most Teams Do WrongThe Better WayWhy It Matters
Version selectionForce HTTP/2 everywhereHTTP/2 for many-stream clients, HTTP/1.1 for simple/embeddedHTTP/2 gains are marginal for low-concurrency single calls
Server pushTry to optimize with pushUse preload hints, push is deprecatedCache-blind push wastes bandwidth, Chrome dropped it
Connection poolingDefault pool sizes untouchedTune pool size + keep-alive to traffic shapePool exhaustion is a silent latency killer under load
HoL awarenessExpect HTTP/2 multiplexing to solve everythingRecognize TCP HoL persists, consider HTTP/3 on lossy pathsMultiplexing breaks under packet loss on mobile
TimeoutsOne global timeoutLayered timeouts (connect, read, total) + retriesA single timeout cannot express the real failure modes

REST

PatternWhat Most Teams Do WrongThe Better WayWhy It Matters
IdempotencyNon-idempotent POSTs with naive retriesIdempotency keys on mutating callsRetries on timeouts double-charge/double-create otherwise
PaginationOffset pagination on large setsCursor/keyset paginationOffset degrades and skips/dupes rows as data shifts
VersioningBreak fields in placeAdditive changes, version only on true breaksSilent breaking changes take down consumers
CachingIgnore HTTP cache headersETags, Cache-Control, conditional requestsREST's caching edge is wasted without them
Error contractsInconsistent ad-hoc error bodiesStandardized problem+json error shapeClients cannot handle errors they cannot parse

gRPC

PatternWhat Most Teams Do WrongThe Better WayWhy It Matters
DeadlinesNo deadlines set on callsSet + propagate deadlines through the chainWithout them, a slow dependency cascades to exhaustion
Load balancingL4 round-robin on long-lived HTTP/2 connsL7 or client-side (xDS) balancingL4 pins connections, hammering one backend
Proto evolutionReuse/renumber field tagsNever reuse field numbers, reserve removed onesWire format is positional, reuse corrupts data
Browser accessTry native gRPC from browserConnect-RPC (no proxy) or gRPC-Web + EnvoyBrowsers cannot speak native gRPC, full stop
Streaming lifecycleIgnore half-close and backpressureHandle flow control + clean stream teardownLeaked/stalled streams exhaust server resources

GraphQL

PatternWhat Most Teams Do WrongThe Better WayWhy It Matters
N+1 resolversOne DB call per fieldDataLoader batch + cache per requestN+1 is GraphQL's default performance disaster
Query costAccept arbitrary queriesDepth + complexity limits, persisted queriesUnbounded queries are a trivial DoS vector
Introspection in prodLeave it enabledDisable or gate it in productionIt hands attackers your full schema map
CachingAssume HTTP caching worksPersisted queries + field/CDN caching (APQ)POST-to-one-endpoint kills normal HTTP caching
Error monitoringAlert on HTTP statusParse the errors array (status is always 200)Failures are invisible to status-based monitoring

WebSocket / SSE

PatternWhat Most Teams Do WrongThe Better WayWhy It Matters
Protocol choiceReach for WebSocket by reflexSSE if push is one-way, WebSocket only if client pushesSSE is simpler, HTTP-native, auto-reconnecting
Reconnect stormsImmediate reconnect on dropJittered exponential backoffSynchronized reconnect after deploy DDoSes you
Cross-node broadcastAssume one server holds all clientsPub/sub backplane (Redis/Kafka/NATS)Clients on different nodes never see each other's messages
HeartbeatsNo keepalive, rely on TCPApp-level ping/pong + idle timeoutDead connections linger, intermediaries silently drop idle ones
SSE on HTTP/1.1Many SSE streams on HTTP/1.1Run SSE over HTTP/2HTTP/1.1's 6-conn-per-origin cap throttles streams

WebRTC

PatternWhat Most Teams Do WrongThe Better WayWhy It Matters
TURN planningAssume pure P2P, skip TURNAlways provision TURN relay + budget egressSymmetric NATs force relay, no-TURN means failed calls
Group scalingFull-mesh for group callsSFU past ~4-6 peersMesh is O(n^2), melts client uplinks
Data-only useUse WebRTC just for a data channelUse WebTransport/WebSocket insteadThe media stack is huge overhead for plain data
SignalingExpect WebRTC to handle setupBuild signaling (usually over WebSocket)WebRTC does media, not session establishment
Network resilienceNo fallback for UDP-blocked netsTURN-over-TCP/TLS fallback pathCorporate firewalls block UDP, calls die without it

8. Advanced / Next-Gen Alternatives

Successors, adjacent tech that does it better for specific cases, and patterns that obviate the original. Maturity as of mid-2026.

TCP / UDP / TLS

Successor / AlternativeWhat It ImprovesMaturityMigration CostWhen To Consider
QUIC (over UDP)Per-stream delivery, no TCP HoL, 0-RTT, connection migrationProductionMedium, via HTTP/3Lossy mobile networks, latency-sensitive web
TLS 1.31-RTT handshake, forward secrecy mandatory, weak ciphers removedProductionLow, mostly configAlways, if still on 1.2
MASQUEProxying/tunneling over QUIC (modern VPN primitive)EmergingHighPrivacy proxies, modern tunneling
Post-quantum TLS (ML-KEM hybrids)Resistance to future quantum key-recoveryEmergingMedium, hybrid rollout underwayLong-lived secrets, harvest-now-decrypt-later threat models

HTTP/1.1 / HTTP/2

Successor / AlternativeWhat It ImprovesMaturityMigration CostWhen To Consider
HTTP/3 (over QUIC)Eliminates transport HoL, faster handshake, connection migrationProductionMedium, needs QUIC-capable stack + UDP egressMobile-heavy, lossy networks, tail-latency-sensitive
gRPC (on HTTP/2)Typed contracts + streaming on top of HTTP/2ProductionMediumInternal service-to-service
HTTP/3 0-RTTNear-instant reconnection for return visitorsProductionLow once on HTTP/3Repeat-visit latency optimization

REST / gRPC / GraphQL

Successor / AlternativeWhat It ImprovesMaturityMigration CostWhen To Consider
Connect-RPCgRPC semantics that work natively in browsers, no Envoy proxy, debuggableProductionLow if already on protobufBrowser clients needing gRPC-style contracts
tRPCEnd-to-end TypeScript type safety, no codegenProductionLow (TS-only stacks)Full-stack TypeScript monorepos
GraphQL FederationOrg-scale schema composition across team-owned subgraphsProductionHigh (org coordination)Many teams, one unified graph
gRPC-WebBrowser access to gRPC backends (unary + server-stream)ProductionMedium (proxy required)Existing gRPC backend, browser must call it

WebSocket / SSE / WebRTC

Successor / AlternativeWhat It ImprovesMaturityMigration CostWhen To Consider
WebTransport (over HTTP/3)Multiplexed streams + unreliable datagrams on one QUIC connection, no TCP HoLEmerging (~75% browser, Safari 26.4 closed the gap)High (HTTP/3 server, UDP egress, fallback)Need mixed reliable/unreliable channels, lossy networks; keep WebSocket fallback
WebSocket over HTTP/3 (RFC 9220)WebSocket semantics on QUIC, dodging TCP HoLEarly (no major browser/server shipped as of 2026)Unknown, not yet practicalFuture, when ecosystem ships it
WebRTC SFU architecturesScales group media past mesh limitsProductionMedium (run/buy an SFU)Group calls beyond a handful of peers
WebTransport datagrams (vs WebRTC data)Simpler low-latency data path without WebRTC's media stackEmergingMediumLow-latency data-only needs (games, telemetry)
Analysis grounded in current protocol specs and operator experience as of 2026-05-22. Browser-support and maturity claims (WebTransport ~75%, WebSocket-over-HTTP/3 unshipped, Connect-RPC) reflect early-to-mid 2026 state. Verify version-specific behavior against current docs before production decisions.