Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

HTTP/2 no Node.js: Guia Prático

Atualizado em: 1 de agosto de 2026

Rack de servidores processando fluxos de dados no Node.js

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.

Os 10 Melhores Cursos de Programação de 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita