Module A-22·26 min read

HTTP/2 multiplexing vs HTTP/1.1 head-of-line blocking, Node.js http2 module, Fastify HTTP/2 setup, server push for resource preloading, gRPC over HTTP/2 with Protocol Buffers, h2c (cleartext) vs h2 (TLS), and the protocol selection decision matrix: REST/HTTP1.1 vs REST/HTTP2 vs gRPC vs WebSocket vs SSE by latency, payload size, and client type.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module 21 — HTTP/2, gRPC Transport, and Protocol Selection

What this module covers: In 2015, HTTP/2 became a standard. In 2025, most Node.js internal APIs still use HTTP/1.1. Not because HTTP/2 is hard — Node.js has native HTTP/2 support. Because nobody told the engineers it was an option, or why it matters. This module gives you the mental model to make the right protocol decision for every service boundary.


What HTTP/1.1 Gets Wrong

HTTP/1.1 has head-of-line blocking at the TCP level. To send request B, you must wait for response A to complete (or open a new connection). Browsers work around this by opening 6 connections per origin. Server-to-server communication typically uses 1 connection, or a small pool.

For an API that returns 10 resources from 10 endpoints, HTTP/1.1 requires 10 sequential round trips (or 10 parallel connections). At 20ms per round trip, that's 200ms minimum.

HTTP/2 multiplexes multiple requests over a single TCP connection. All 10 requests go out in the same TCP segment. All 10 responses come back as soon as the data is ready. Total time: 20ms + max(data fetch times).


HTTP/2 in Node.js

Native HTTP/2 module — no dependencies:

javascript

Fastify with HTTP/2 (recommended — production-ready):

javascript

No application-level code changes needed. Fastify handles the HTTP/2 protocol transparently.

ALPN: How Client and Server Actually Agree on h2 vs HTTP/1.1

The examples above all run HTTP/2 over TLS on the same port (443) that HTTP/1.1 traditionally uses. Client and server agree on which protocol to actually speak using ALPN (Application-Layer Protocol Negotiation), a TLS extension: during the TLS handshake, the client sends a list of protocols it supports (typically ["h2", "http/1.1"]), and the server picks one from that list and confirms it before the handshake completes. Only after ALPN has settled on h2 does either side start speaking the HTTP/2 binary framing layer — this is why createSecureServer needs no special "port routing" logic to support both protocols simultaneously; it's negotiated once, up front, inside the TLS handshake itself, not sniffed from the first bytes of application data.

javascript

Cleartext (non-TLS) connections have no TLS handshake at all, so there's no ALPN to negotiate — which is exactly the gap h2c (below) has to solve differently.

h2c: Cleartext HTTP/2 (Server-to-Server)

Everything shown so far is h2 — HTTP/2 over TLS, which is what browsers require. For trusted server-to-server traffic inside a private network (indexer-to-indexer, service-to-service behind a service mesh that already handles encryption at another layer), h2c runs the same HTTP/2 framing over a plain, unencrypted TCP connection — no certificates, no ALPN:

javascript
javascript

Because there's no ALPN to fall back on, h2c requires both ends to have prior, out-of-band knowledge that the peer speaks HTTP/2 — there is no graceful negotiation or fallback to HTTP/1.1 mid-connection. This is fine for two services you deploy together, and inappropriate for anything facing an unknown or public client.

Client-Side HTTP/2: http2.connect() and Session Lifecycle

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.