Summary

Node.js v18 builds in HTTP/2 via the core http2 module and ships experimental QUIC (HTTP/3) support behind a flag. HTTP/2 brings multiplexed streams, header compression, and server push to your apps, while QUIC leverages UDP, 0-RTT handshakes, and improved loss recovery for lower-latency connections (nodejs.org, nodejs.org).

1. Introduction

HTTP/2, standardized in 2015, addresses HTTP/1.1’s head-of-line blocking by allowing multiple request/response pairs over a single TCP connection using multiplexing and HPACK header compression (stackoverflow.com, devcrud.com). HTTP/3 (QUIC) moves this model to UDP, adding built-in TLS 1.3, 0-RTT reconnects, and connection migration for mobile clients (javascript-conference.com). Before Node.js v18, you had to rely on reverse proxies (like Nginx, Envoy) or external modules to get HTTP/2 or QUIC support.

2. HTTP/2 in Node.js v18

2.1 Enabling HTTP/2

Require the built-in module or import in ESM:

// CommonJS
const http2 = require('node:http2');
// ESM
import http2 from 'node:http2';

For a secure server, use createSecureServer with TLS certs:

import fs from 'fs';
import http2 from 'node:http2';

const server = http2.createSecureServer({
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem'),
});
server.listen(8443);

(nodejs.org, nodejs.org)

2.2 Key Features

  • Multiplexing: Multiple HTTP streams share a single TCP connection, eliminating head-of-line blocking at the HTTP layer (stackoverflow.com).
  • HPACK Compression: Headers are compressed efficiently, reducing overhead on repeated headers (nodejs.org).
  • Server Push: Servers can proactively send resources to clients before an explicit request, useful for linked assets like CSS or JS (blog.risingstack.com).

2.3 Example

import fs from 'fs';
import http2 from 'node:http2';

const server = http2.createSecureServer({
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem')
});
server.on('stream', (stream, headers) => {
  stream.pushStream({ ':path': '/style.css' }, (err, pushStream) => {
    pushStream.end('body { background: #fafafa }');
  });
  stream.end('<h1>Hello HTTP/2</h1>');
});
server.listen(8443);

(nodejs.org)

3. QUIC (HTTP/3) Experimental Support

3.1 Under the Hood

QUIC support in Node.js v18 is experimental and lives behind the --experimental-quic flag. It uses a user-space QUIC implementation built atop OpenSSL/QuicTLS, combining UDP transport, TLS 1.3, and multiplexed streams in one protocol (nearform.com).

3.2 Enabling QUIC

Start your app with QUIC enabled:

node --experimental-quic index.js

For fetch() over QUIC, also enable the experimental fetch API:

node --experimental-quic --experimental-fetch index.js

(nearform.com)

3.3 Example Snippet

import { createQuicSocket } from 'node:net';

(async () => {
  const socket = createQuicSocket({ endpoint: { address: '0.0.0.0', port: 4433 } });
  await socket.listen();

  for await (const session of socket) {
    session.on('stream', stream => {
      stream.write('HTTP/3 Hello World');
      stream.end();
    });
  }
})();

(nodejs.org)

4. Performance Tuning & Metrics

  • 0-RTT Handshakes: QUIC’s 0-RTT feature lets returning clients resume connections with zero round trips, drastically reducing latency on reconnections (javascript-conference.com).
  • TLS Session Reuse: Both HTTP/2 and QUIC benefit from TLS session tickets for fast reconnects (linkedin.com).
  • Latency & Throughput: Benchmark HTTP/1.1, HTTP/2, and QUIC using tools like wrk or hey to compare RTTs, requests/sec, and CPU usage (linkedin.com).

5. Pitfalls & Best Practices

  • API Maturity: The QUIC API is experimental and subject to change; avoid using it in production until stable APIs land (nearform.com).
  • Certificate Management: Ensure ALPN negotiation includes h3 and fallback to h2 or http/1.1 for clients that don’t support QUIC (nodejs.org).
  • Monitoring & Fallback: Use health checks and metrics to detect QUIC failures and gracefully fallback to HTTP/2 to maintain availability (javascript-conference.com).

6. Full Walkthrough

  1. Create self-signed certs:

    openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out cert.pem
    
  2. Implement both HTTP/2 and QUIC servers as shown above.

  3. Benchmark with wrk:

    wrk -t4 -c100 -d20s https://localhost:8443
    wrk -t4 -c100 -d20s quic://localhost:4433
    
  4. Compare latency percentiles and requests/sec in the results.

7. Conclusion & Further Reading

HTTP/2 in Node.js v18 brings first-class support for multiplexing, header compression, and server push without extra proxies, while experimental QUIC unlocks UDP-based, low-latency connections with built-in TLS and 0-RTT. Monitor performance and use fallback strategies to keep your apps resilient.

Further Reading