O HTTP/2 foi criado para reduzir limitações do HTTP/1.1, permitindo multiplexar várias requisições na mesma conexão, compactar cabeçalhos e priorizar fluxos. O módulo HTTP/2 no Node.js, disponível como node:http2, permite construir clientes e servidores compatíveis com o protocolo sem dependências externas.
Adotar HTTP/2 não significa que toda aplicação ficará automaticamente mais rápida. O ganho depende da rede, do proxy, da quantidade de recursos e da forma como o servidor controla streams. Também é necessário configurar TLS, limites, timeouts e compatibilidade com HTTP/1.1.
Neste guia, você aprenderá a criar um servidor seguro, responder a streams, usar a API compatível com request e response, configurar sessões, consumir serviços HTTP/2 e evitar erros comuns.
O que muda no HTTP/2?
No HTTP/1.1, navegadores abrem várias conexões para contornar limitações de concorrência. No HTTP/2, uma única conexão transporta múltiplos fluxos independentes. Cada stream possui identificador e pode avançar sem esperar o término das demais.
A documentação oficial de HTTP/2 no Node.js detalha sessões, streams e opções. A especificação atual pode ser consultada no RFC 9113.
Para revisar a criação de endpoints, veja como criar uma API com Node.js e o artigo sobre o que é Node.js.
Criando um servidor HTTP/2 seguro
const http2 = require('node:http2');
const fs = require('node:fs');
const server = http2.createSecureServer({
key: fs.readFileSync('./certs/key.pem'),
cert: fs.readFileSync('./certs/cert.pem')
});
server.on('stream', (stream, headers) => {
const path = headers[':path'];
if (path === '/') {
stream.respond({
':status': 200,
'content-type': 'application/json'
});
stream.end(JSON.stringify({ status: 'ok' }));
return;
}
stream.respond({ ':status': 404 });
stream.end();
});
server.listen(8443);Os campos iniciados por dois-pontos são pseudoheaders do protocolo. :path, :method e :status devem ser tratados de acordo com as regras do HTTP/2.
Compatibilidade com HTTP/1.1
Com allowHTTP1: true, o servidor TLS pode aceitar clientes que não negociam HTTP/2 por ALPN:
const server = http2.createSecureServer({
key,
cert,
allowHTTP1: true
});
server.on('request', (req, res) => {
res.setHeader('content-type', 'application/json');
res.end(JSON.stringify({ protocol: req.httpVersion }));
});A API request/response é semelhante ao módulo HTTP tradicional e facilita integração com bibliotecas. Evite responder ao mesmo fluxo tanto pelo evento stream quanto por request.
Servidor HTTP/2 sem TLS
createServer() cria HTTP/2 em texto claro, conhecido como h2c:
const server = http2.createServer();Navegadores geralmente exigem HTTP/2 sobre TLS. h2c é mais comum em comunicação interna ou entre proxy e aplicação, com infraestrutura controlada.
Criando um cliente
const client = http2.connect('https://localhost:8443', {
rejectUnauthorized: false
});
const request = client.request({
':path': '/',
':method': 'GET'
});
const chunks = [];
request.on('data', chunk => chunks.push(chunk));
request.on('end', () => {
const body = Buffer.concat(chunks).toString('utf8');
console.log(body);
client.close();
});
request.end();rejectUnauthorized: false serve apenas para certificado local de teste. Em produção, valide a cadeia de confiança.
Reutilizando a sessão
O principal benefício aparece quando várias requisições compartilham a mesma sessão:
async function requestPath(client, path) {
return new Promise((resolve, reject) => {
const request = client.request({ ':path': path });
const chunks = [];
request.on('response', headers => {
if (headers[':status'] >= 400) {
reject(new Error(`HTTP ${headers[':status']}`));
}
});
request.on('data', chunk => chunks.push(chunk));
request.on('end', () => resolve(Buffer.concat(chunks)));
request.on('error', reject);
request.end();
});
}Crie um pool ou gerenciador que feche sessões ociosas e abra uma nova conexão quando a atual estiver drenando ou encerrada.
Streams e backpressure
Uma Http2Stream é Duplex. Ao enviar dados grandes, respeite o retorno de write() e o evento drain. Para arquivos, use pipeline():
const { pipeline } = require('node:stream');
server.on('stream', (stream, headers) => {
if (headers[':path'] !== '/download') return;
stream.respond({
':status': 200,
'content-type': 'application/octet-stream'
});
pipeline(
fs.createReadStream('./large.zip'),
stream,
error => {
if (error) console.error(error);
}
);
});Para aprofundar o tema, consulte Streams no Node.js.
Limites de concorrência
Uma conexão pode abrir muitos streams. Configure limites no servidor e no proxy para impedir abuso. Monitore streams ativos, tamanho de cabeçalhos, tempo de resposta e bytes em trânsito.
const server = http2.createSecureServer({
key,
cert,
settings: {
maxConcurrentStreams: 100,
maxHeaderListSize: 16 * 1024
}
});Os valores ideais dependem do consumo de memória e do perfil das rotas.
Tratando erros de sessão e stream
server.on('sessionError', error => {
console.error('Erro de sessão:', error);
});
server.on('stream', stream => {
stream.on('error', error => {
console.error('Erro de stream:', error);
});
});Uma falha em um stream não significa necessariamente que toda a sessão deve ser encerrada. Registre o código e a origem antes de decidir.
Timeouts
Defina timeouts para sessões ociosas e operações individuais:
server.on('session', session => {
session.setTimeout(30_000, () => {
session.close();
});
});Em clientes, combine timeout com AbortController no Node.js e uma política de retry limitada.
Encerramento gradual
Durante deploy, pare de aceitar novas conexões e envie GOAWAY para sessões existentes:
server.close();
for (const session of activeSessions) {
session.close();
}A aplicação deve aguardar streams em andamento até um limite e então destruir sessões remanescentes. Isso evita interromper respostas no meio.
Server Push
HTTP/2 possui server push, mas navegadores modernos reduziram ou removeram suporte por baixa eficiência em muitos cenários. Não baseie a arquitetura nesse recurso sem confirmar o cliente. Prefira cache, preload e distribuição adequada de recursos.
Proxy reverso
Em produção, Nginx, Envoy, CDN ou load balancer frequentemente termina TLS e HTTP/2. A comunicação até o Node.js pode ser HTTP/1.1 ou h2c. Confirme qual protocolo existe em cada trecho antes de atribuir problemas ao aplicativo.
O artigo sobre performance de APIs Node.js apresenta métricas e otimizações complementares.
Segurança de cabeçalhos
Valide método, caminho, autoridade e tamanho. Não copie todos os headers recebidos para uma resposta. Pseudoheaders devem aparecer antes de campos normais e não podem ser duplicados de forma inválida.
Testando HTTP/2
Use um certificado local confiável ou ferramenta de teste. Confirme negociação ALPN, múltiplos streams simultâneos, respostas grandes, cancelamento, GOAWAY e fallback HTTP/1.1. Teste também por meio do proxy real.
Erros comuns
- Abrir uma sessão por requisição: perde multiplexação e aumenta handshake.
- Desativar validação TLS em produção: permite ataques intermediários.
- Ignorar backpressure: buffers crescem com clientes lentos.
- Não limitar streams: uma conexão pode consumir recursos excessivos.
- Assumir que o proxy usa HTTP/2 até o Node: o protocolo pode terminar antes.
- Usar server push sem medir: transfere recursos desnecessários.
- Não tratar GOAWAY: clientes tentam reutilizar sessão em encerramento.
Boas práticas para produção
- Reutilize sessões no cliente.
- Use TLS válido e configuração moderna.
- Defina limites de streams e headers.
- Aplique timeouts e encerramento gradual.
- Use streams para respostas grandes.
- Monitore sessões, latência e erros por código.
- Teste fallback HTTP/1.1.
- Confirme a arquitetura do proxy.
- Não dependa de server push.
- Faça testes de carga com multiplexação real.
Conclusão
O HTTP/2 no Node.js permite construir comunicação multiplexada com controle de sessões e streams. O módulo nativo oferece API de baixo nível e uma interface compatível com request e response.
O melhor resultado vem da combinação entre sessão reutilizada, TLS correto, limites, backpressure e observabilidade. Meça o caminho completo, incluindo proxy e cliente, antes de concluir que a troca de protocolo resolveu ou criou um problema de desempenho.




