Advanced

HTTP/2 Sessions

Rezo supports HTTP/2 through a dedicated adapter. HTTP/2 multiplexes multiple requests over a single TCP connection, eliminating the overhead of opening separate connections for each request.

Enabling HTTP/2

Import the HTTP/2 adapter and create a client:

import rezo from 'rezo/adapters/http2';

const client = rezo.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
});

// All requests share a single TCP connection via HTTP/2 multiplexing
const [users, posts, comments] = await Promise.all([
  client.get('/users'),
  client.get('/posts'),
  client.get('/comments'),
]);

Benefits of HTTP/2

  • Multiplexing: Send many requests in parallel over one connection. No head-of-line blocking at the HTTP layer.
  • Header compression: HPACK compression reduces header overhead, especially for APIs with repetitive headers.
  • Server push: Servers can proactively send resources the client will need.
  • Single connection: One TCP+TLS handshake per host, regardless of how many parallel requests you make.

Automatic Session Reuse

Rezo pools and reuses HTTP/2 sessions automatically. When you make multiple requests to the same host, they share the same session:

// Request 1: Opens a new HTTP/2 session to api.example.com
await client.get('/users');

// Request 2: Reuses the existing session (no new TCP+TLS handshake)
await client.get('/posts');

// Request 3: Still the same session
await client.get('/comments');

Sessions are keyed by host. Requests to different hosts use separate sessions. Requests through different proxies also get separate sessions.

GOAWAY Handling

When a server sends a GOAWAY frame (e.g., during a server restart or load rebalancing), Rezo handles it automatically:

  1. The existing session is marked as closing
  2. In-flight requests on that session complete normally
  3. The next request to the same host opens a fresh session
// If the server sends GOAWAY between these requests,
// Rezo creates a new session transparently
await client.get('/data');
await client.get('/more-data'); // Fresh session if GOAWAY was received

You do not need to handle GOAWAY errors in your application code.

ALPN Verification — No Silent Downgrade

The HTTP/2 adapter offers h2 and http/1.1 in its ALPN list, but it errors out if the server does not negotiate h2 after the TLS handshake. There is no silent downgrade:

try {
  await client.get('https://http1-only-server.com/data');
} catch (err) {
  // err.code is the underlying ALPN failure — the request never reaches HTTP/2 layer
}

This is intentional: applications that opt in to the HTTP/2 adapter are usually relying on multiplexing and want to know up-front when an origin won’t honor it. If you want graceful protocol negotiation, use the default HTTP adapter (rezo from 'rezo' or 'rezo/adapters/http') which does HTTP/1.1 with optional Upgrade.

Proxy Support

HTTP/2 works through proxies. Rezo establishes a tunnel through the proxy before starting the HTTP/2 session:

const client = rezo.create({
  baseURL: 'https://api.example.com',
  proxy: {
    protocol: 'http',
    host: 'proxy.company.com',
    port: 8080,
  },
});

await client.get('/data');
// Connects to proxy → tunnels via CONNECT → starts HTTP/2 session

SOCKS4 and SOCKS5 proxies are also supported.

Idle Session Cleanup

Sessions that are no longer in use are cleaned up automatically. After a period of inactivity (approximately 60 seconds with no in-flight requests), idle sessions are closed. The cleanup timer does not prevent Node.js from exiting, so it is safe to use in short-lived scripts without explicit teardown.

Stealth Profile Integration

When using a stealth profile, HTTP/2 session settings are configured to match the selected browser automatically:

import rezo from 'rezo/adapters/http2';
import { RezoStealth } from 'rezo';

// Pass the stealth instance through `stealth` on the instance config —
// the adapter applies the resolved profile (TLS, h2 settings, header order)
// to every request automatically.
const client = rezo.create({
  stealth: new RezoStealth({ profile: 'chrome-131' })
});

await client.get('https://example.com');
// HTTP/2 SETTINGS, header order, and TLS fingerprint match Chrome 131

Debug Logging

Enable debug mode to see HTTP/2 session lifecycle events:

const response = await client.get('/data', { debug: true });
// [Rezo Debug] HTTP/2: Creating new session to https://api.example.com
// [Rezo Debug] HTTP/2: Reusing session for https://api.example.com
// [Rezo Debug] HTTP/2: Session GOAWAY received

When to Use HTTP/2

HTTP/2 is a good fit when:

  • Making many requests to the same host (API clients, crawlers, scrapers)
  • The server supports HTTP/2 (most modern servers do)
  • You want parallel requests without opening multiple connections
  • Header overhead matters (repeated headers are compressed)

Stick with HTTP/1.1 when:

  • Targeting servers that do not support HTTP/2
  • You need maximum compatibility with older infrastructure