HTTP/2 in Node.js: Core API, Sessions, and Streams

The node:http2 module provides a stable implementation of the HTTP/2 protocol in Node.js. . Unlike the HTTP/1 API, the HTTP/2 Core API is designed specifically for protocol features such as multiplexed streams, server push, and advanced flow control. It offers a symmetric design between client and server, with events like stream, error, and connect available on both sides. Developers can use secure servers (http2.createSecureServer) for browser compatibility, and clients can connect using http2.connect.

http2 Core API / Compatibility APIHttp2Session / ServerHttp2Session / ClientHttp2SessionHttp2Stream lifecycleEvents: stream, goaway, ping, settings, timeoutserver push / ALTSVC / ORIGIN frames

~9 min read • Updated Dec 29, 2025

1. Introduction


The http2 module is accessed via require('node:http2'). It provides a low-level Core API for HTTP/2 features and a Compatibility API for easier migration from HTTP/1.


2. Server Example


const http2 = require('node:http2');
const fs = require('node:fs');

const server = http2.createSecureServer({
  key: fs.readFileSync('localhost-privkey.pem'),
  cert: fs.readFileSync('localhost-cert.pem'),
});

server.on('stream', (stream, headers) => {
  stream.respond({ 'content-type': 'text/html; charset=utf-8', ':status': 200 });
  stream.end('

Hello World

'); }); server.listen(8443);

3. Client Example


const http2 = require('node:http2');
const fs = require('node:fs');

const client = http2.connect('https://localhost:8443', {
  ca: fs.readFileSync('localhost-cert.pem'),
});

const req = client.request({ ':path': '/' });
req.on('response', (headers) => {
  for (const name in headers) console.log(`${name}: ${headers[name]}`);
});
req.setEncoding('utf8');
let data = '';
req.on('data', (chunk) => { data += chunk; });
req.on('end', () => { console.log(data); client.close(); });
req.end();

4. Http2Session


Http2Session represents an active communication session between client and server. It manages settings, flow control, and multiplexed streams. Key events include:


  • close: Fired when the session is destroyed.
  • connect: Fired when the session connects to a peer.
  • error: Fired on session errors.
  • goaway: Fired when a GOAWAY frame is received.
  • stream: Fired when a new Http2Stream is created.
  • timeout: Fired when no activity occurs after a set timeout.

5. Http2Stream Lifecycle


Http2Stream instances represent bidirectional streams over a session. They are created when:


  • Server receives a new HEADERS frame.
  • Client calls session.request().
  • Server or client initiates a push stream.

Streams are destroyed when close(), destroy(), or RST_STREAM frames are used.


6. Advanced Features


  • ALTSVC: Advertises alternative services (RFC 7838).
  • ORIGIN: Advertises authoritative origins (RFC 8336).
  • ping(): Sends a PING frame to measure latency.
  • settings(): Updates local settings and waits for acknowledgment.

7. Example: Server Push


server.on('stream', (stream) => {
  stream.respond({ ':status': 200 });
  stream.pushStream({ ':path': '/style.css' }, (err, pushStream) => {
    if (err) throw err;
    pushStream.respond({ ':status': 200, 'content-type': 'text/css' });
    pushStream.end('body { color: red; }');
  });
  stream.end('');
});

Conclusion


The http2 module in Node.js enables developers to build modern, efficient, and secure applications using HTTP/2 features such as multiplexed streams, server push, and advanced flow control. By leveraging Http2Session and Http2Stream, developers gain precise control over client-server communication.


1. Http2Stream Properties


  • aborted: Indicates abnormal termination of the stream.
  • bufferSize: Number of characters currently buffered for writing.
  • closed: True if the stream has been closed.
  • destroyed: True if the stream has been destroyed and is no longer usable.
  • endAfterHeaders: Indicates no additional data will be received after headers.
  • id: Numeric identifier of the stream.
  • pending: True if the stream has not yet been assigned an ID.
  • rstCode: RST_STREAM error code when destroyed.

2. Header and Trailer Management


  • sentHeaders: Outbound headers sent for the stream.
  • sentInfoHeaders: Additional informational headers sent.
  • sentTrailers: Outbound trailers sent.
  • sendTrailers(headers): Sends trailing headers after the wantTrailers event.

3. Timeout and State Management


  • setTimeout(msecs, callback): Sets a timeout for the stream.
  • state: Provides details such as window size and close status.

4. ClientHttp2Stream


The client variant of Http2Stream handles events such as:


  • continue: Fired when a 100 Continue status is received.
  • headers: Fired when informational headers are received.
  • push: Fired when server push headers are received.
  • response: Fired when the main response headers are received.

5. ServerHttp2Stream


The server variant of Http2Stream provides methods such as:


  • respond(headers[, options]): Initiates a response to the client.
  • pushStream(headers[, options], callback): Creates a push stream to send additional data.
  • respondWithFD(fd[, headers[, options]]): Sends response data from a file descriptor.
  • respondWithFile(path[, headers[, options]]): Sends a file as the response.

6. Http2Server and Http2SecureServer


These classes manage HTTP/2 servers and provide events such as request, session, stream, and timeout. The secure variant (Http2SecureServer) uses TLS for encrypted communication.


7. Example


const http2 = require('node:http2');
const server = http2.createServer();

server.on('stream', (stream) => {
  stream.respond({ ':status': 200 });
  stream.end('Hello from HTTP/2 stream');
});

server.listen(8000);

Conclusion


The Http2Stream class and its client/server variants in Node.js provide powerful tools for managing HTTP/2 streams. These features enable developers to build faster, more secure, and efficient applications with support for server push and direct file responses.


1. Key Events


  • timeout: Fired when there is no activity on the server for a specified duration.
  • unknownProtocol: Fired when a client fails to negotiate an allowed protocol (HTTP/2 or HTTP/1.1).

2. Server Management


  • server.close([callback]): Stops new sessions and gracefully shuts down the server.
  • server.setTimeout([msecs][, callback]): Sets a timeout for server requests.
  • server.timeout: Inactivity timeout before a socket is presumed closed.
  • server.updateSettings([settings]): Updates server settings.

3. Creating an HTTP/2 Server


  • http2.createServer([options][, handler]): Creates an unencrypted HTTP/2 server.
  • http2.createSecureServer(options[, handler]): Creates a secure HTTP/2 server using TLS.

4. Client Connections


http2.connect(authority[, options][, listener]) connects a client to an HTTP/2 server and returns a ClientHttp2Session instance.


5. Error Codes (http2.constants)


Error codes for RST_STREAM and GOAWAY frames include:


  • NGHTTP2_NO_ERROR: No error.
  • NGHTTP2_PROTOCOL_ERROR: Protocol error.
  • NGHTTP2_INTERNAL_ERROR: Internal error.
  • NGHTTP2_FLOW_CONTROL_ERROR: Flow control error.
  • NGHTTP2_CANCEL: Stream canceled.
  • NGHTTP2_ENHANCE_YOUR_CALM: Error due to misbehaving client.

6. Header Management


  • Headers are represented as key-value pairs in JavaScript objects.
  • Header names are transmitted in lowercase.
  • Sensitive headers (e.g., Cookie, Authorization) can be marked with http2.sensitiveHeaders to avoid indexing in compression.
  • Raw headers format preserves ordering and duplicates for proxy use cases.

7. Example


const http2 = require('node:http2');
const fs = require('node:fs');

const options = {
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem'),
};

const server = http2.createSecureServer(options);

server.on('stream', (stream, headers) => {
  stream.respond({ 'content-type': 'text/html; charset=utf-8', ':status': 200 });
  stream.end('

Hello World

'); }); server.listen(8443);

Conclusion


Managing events and settings in HTTP/2 servers in Node.js allows developers to build secure, stable, and flexible servers. With methods like setTimeout and updateSettings, and events like timeout and unknownProtocol, developers gain precise control over the communication lifecycle.


1. Push Streams on the Client


To receive pushed streams on the client, set a listener for the stream event on ClientHttp2Session. These streams deliver additional data from the server without direct client requests.


2. Supporting the CONNECT Method


The CONNECT method allows an HTTP/2 server to act as a proxy for TCP/IP connections. The server validates CONNECT requests and establishes direct connections to the target. Clients can send CONNECT requests to the proxy to initiate tunneling.


3. Extended CONNECT Protocol (RFC 8441)


This protocol enables using CONNECT streams as tunnels for other communication protocols (e.g., WebSockets). Servers must enable enableConnectProtocol, and clients can then send CONNECT requests with the :protocol pseudo-header after receiving the SETTINGS frame.


4. Compatibility API


The Compatibility API provides an HTTP/1-like developer experience, allowing applications to support both HTTP/1 and HTTP/2. Classes Http2ServerRequest and Http2ServerResponse are designed for this purpose, though they do not hide protocol differences.


5. ALPN Negotiation


ALPN negotiation allows supporting both HTTPS and HTTP/2 over the same socket. With the allowHTTP1 option, servers can accept HTTP/1 requests alongside HTTP/2, enabling hybrid deployments.


6. Http2ServerRequest


This class represents incoming requests on an HTTP/2 server. Key properties include:


  • aborted: Indicates abnormal termination of the request.
  • headers: Request headers object.
  • httpVersion: HTTP version (typically 2.0).
  • method: Request method (GET, POST, DELETE).
  • url: Request path string.

7. Http2ServerResponse


This class represents outgoing responses from the server. Key methods and properties include:


  • addTrailers(headers): Adds trailing headers.
  • appendHeader(name, value): Appends a new value to an existing header.
  • createPushResponse(headers, callback): Creates a push response.
  • end([data]): Ends the response.
  • getHeader(name), getHeaders(): Retrieve headers.
  • setHeader(name, value): Set a header.
  • setTimeout(msecs, callback): Set a timeout for the response.

8. Example


const http2 = require('node:http2');

const server = http2.createServer((req, res) => {
  res.setHeader('Content-Type', 'text/html; charset=utf-8');
  res.writeHead(200);
  res.end('Hello from HTTP/2');
});

server.listen(8000);

Conclusion


HTTP/2 client and server features in Node.js provide powerful tools for managing push streams, CONNECT proxies, and compatibility with HTTP/1. These capabilities enable developers to build modern, secure, and flexible applications.


1. Core Properties


  • response.statusCode: Sets or reflects the status code when using implicit headers. After headers are sent, it shows the actual status code.
  • response.statusMessage: Not supported in HTTP/2; always returns an empty string.
  • response.stream: The Http2Stream object backing the response.
  • writableEnded: True after end() has been called.

2. Sending Data


  • response.write(chunk[, encoding][, callback]): Sends part of the response body. If writeHead() has not been called, it switches to implicit header mode.
  • Can be called multiple times to send successive chunks of data.
  • HEAD requests, and responses with status 204 or 304, must not include a body.

3. Special Methods


  • response.writeContinue(): Sends a 100 Continue status to indicate the request body should be sent.
  • response.writeEarlyHints(hints): Sends a 103 Early Hints status with Link headers for resource preloading.
  • response.writeHead(statusCode[, statusMessage][, headers]): Sends response headers with a status code. May be called only once before end().

4. Header Management


  • Headers set with setHeader() are merged with those passed to writeHead(), with writeHead() taking precedence.
  • Content-Length must be specified in bytes. Node.js does not validate outbound body length against Content-Length, but inbound messages are validated.

5. Collecting Performance Metrics


The PerformanceObserver API can collect metrics for Http2Session and Http2Stream instances:


  • For streams: bytesRead, bytesWritten, id, timeToFirstByte, timeToFirstHeader.
  • For sessions: framesReceived, framesSent, pingRTT, streamCount, maxConcurrentStreams.

6. Note on :authority and host


HTTP/2 requires either the :authority pseudo-header or the host header. Use :authority when constructing HTTP/2 requests directly, and host when converting from HTTP/1 (e.g., in proxies).


7. Example


const http2 = require('node:http2');

const server = http2.createServer((req, res) => {
  res.setHeader('Content-Type', 'text/plain; charset=utf-8');
  res.writeHead(200);
  res.write('Hello ');
  res.end('World');
});

server.listen(8000);

Conclusion


The Http2ServerResponse class in Node.js provides powerful tools for managing HTTP/2 responses. With methods like writeHead, writeEarlyHints, and writeContinue, developers gain precise control over the response lifecycle, while the Performance Observer API enables monitoring of session and stream performance.


Written & researched by Dr. Shahin Siami