Node.js 26 'Lithium' é LTS: Temporal ligado por padrão, fetch com HTTP/2 e o upgrade que já chegou ao seu CI
Node.js 26 "Lithium" é LTS: Temporal ligado por padrão, fetch com HTTP/2 e o upgrade que já chegou ao seu CI
Em 28 de outubro, a versão 26.13.0 do Node.js foi promovida a Active LTS com o codename Lithium , com correções garantidas até o fim de abril de 2029. A promoção em si não trouxe código novo: as notas de release registram que 26.13.0 é funcionalmente idêntica à 26.12.1 — muda apenas o metadado que marca a linha como LTS. Quem já rodava 26.12 em produção não ganhou comportamento novo naquele dia.
O que faz esse LTS importar não é a data, e sim o pacote que ele carimba. A linha 26 traz o Temporal habilitado por padrão como global , o V8 14.6 (Chromium 146) e o Undici 8 , com HTTP/2 no fetch . São três mudanças com impacto direto em código que hoje funciona: bibliotecas de data, contratos de API com o front, mocks de teste e instrumentação de tracing.
E há um detalhe operacional que quase ninguém planejou. No mesmo 28 de outubro, a tag oficial node:lts do Docker passou de 24 para 26, e o lts/* do actions/setup-node começou a resolver para a nova linha. Ou seja: parte dos times já está rodando Node 26 no CI sem ter decidido isso. Vale conferir hoje o que seu pipeline realmente baixa, antes que a diferença entre "o que testei" e "o que builda" apareça num deploy de sexta.
Temporal: o Date ganha substituto, e o problema deixa de ser invisível
O Date não sai da linguagem — remover um global quebraria a web inteira. O Temporal convive com ele, e a migração é por substituição gradual, arquivo por arquivo. A diferença conceitual é grande: Date é um instante em milissegundos com fuso do processo, mutável e com armadilhas conhecidas (mês indexado em zero, getMonth , comparação por toString ). Temporal separa os tipos: PlainDate para data civil sem hora, ZonedDateTime para data e hora com fuso nomeado, Instant para o instante absoluto, Duration para aritmética.
O ganho maior aparece em código com fuso. Converter reunião entre cidades deixa de depender da máquina onde o processo roda:
Repare na segunda linha: o formato que vai para o banco é decisão de arquitetura, não detalhe . ZonedDateTime.toString() pode sair com o offset e o fuso entre colchetes ( ...[America/Sao_Paulo] ), formato RFC 9557 que colunas timestamptz e parsers de terceiros não aceitam uniformemente. A regra prática: persista Instant (UTC), guarde o fuso como coluna de texto separada quando ele for regra de negócio, e converta na borda — na API e na tela. Em times que atendem várias regiões, esse é o tipo de decisão que a Maquinaweb costuma fechar na modelagem, antes de a primeira data virar bug de cobrança.
HTTP/2 no fetch e o trace que aponta para a requisição errada
O Undici 8 habilita HTTP/2 no fetch nativo, o que é bom para latência e reuso de conexão, mas muda o que passa pelo socket. Dois pontos merecem teste antes de produção: proxies de saída que só falam HTTP/1.1 (comum em ambientes corporativos e em alguns sidecars) e bibliotecas que interceptam o undici para mock — nock , msw e afins. Se o seu conjunto de testes depende de interceptar http.ClientRequest , ele pode simplesmente parar de ver as chamadas feitas com fetch .
Há ainda uma armadilha de observabilidade documentada por quem testou a 26 em produção: em uma rajada fria de fetch HTTPS concorrentes, o Undici despacha as requisições no contexto assíncrono da primeira, e a instrumentação de OpenTelemetry costuma colar várias chamadas em um único trace — em um teste relatado, 19 de 20 chamadas saíram atribuídas ao mesmo trace pai. Não é vazamento de dados, é diagnóstico errado: você olha o gráfico, vê uma chamada lenta e conclui que o problema é no serviço A, quando estava no B. Antes de confiar no latency chart da semana que vem, rode um teste de carga frio com tracing ligado e compare a cardinalidade dos traces.
O que quebra de verdade
APIs removidas entre 24 e 26. Ir de 24 para 26 atravessa todas as mudanças major da linha 25. Rode a suíte com --throw-deprecation para transformar aviso em falha e descubra a lista real do seu código.
Addons nativos. Qualquer dependência compilada contra outra ABI precisa de rebuild ou de versão atualizada. npm rebuild no CI esconde o problema; teste com --ignore-scripts desligado e cache limpo.
Código isomórfico. Temporal é global no Node, mas no navegador ainda não está em todos os engines. Se o mesmo arquivo roda no SSR e no cliente, você precisa de polyfill ( temporal-polyfill ) até o suporte estabilizar — e de lib atualizado no tsconfig para os tipos aparecerem.
Bibliotecas de data. dayjs , date-fns e moment continuam funcionando com Date ; migrar para Temporal é projeto, não bump de versão. Faça por domínio de negócio, com teste de fuso em DST.
Versão implícita no CI. node:lts e lts/* não são pinos. Troque por 26.x ou pelo digest da imagem e deixe a atualização de major como decisão datada.
Node 26 é o último do modelo ímpar/par
Vale registrar para quem define política de runtime: a linha 26 encerra o esquema de duas majors por ano, em que só as pares viravam LTS. A partir do 27 — cujo primeiro alpha, 27.0.0-alpha.0.0.0 , foi publicado em 29 de outubro — passa a haver uma major por ano e toda major se torna LTS . O reflexo prático é que a heurística "use a versão par" morre agora. Times que escreveram essa regra em runbook precisam reescrevê-la.
Recomendação prática
Se você está na 24: ela entrou em manutenção em 20 de outubro e continua recebendo correções — não há incêndio. A janela boa para migrar é esta, com a 26 já madura e a linha recebendo patch (a 26.13.1 saiu em 11/11). Ordem que funciona na prática: pine a versão no CI, rode os testes com deprecation como erro, valide o fetch contra seus mocks e seu proxy, ligue o tracing em ambiente de carga e só então migre o primeiro serviço. Deixe os pontos de data para uma segunda etapa, com testes de DST e de virada de mês em fuso não-UTC.
Se o time está avaliando migrar de runtime, rever a camada de datas ou colocar um serviço novo no ar, o time da Maquinaweb pode ajudar a desenhar essa transição sem parar a esteira de entrega.
Fontes
Continue lendo
Desenvolvimento Rust 1.100: Cargo ganha cooldown de dependências e aviso de crate não usada
Rust 1.100 dá ao Cargo uma idade mínima de publicação para dependências e um aviso nativo de crate não usada no Cargo.toml. O que muda no fluxo de update e no CI, por que o cooldown pode travar correção de segurança e como configurar sem quebrar o build.
Ler artigo →
Desenvolvimento Rspack 2.3: parser SWC Next, cache por loader e menos memória no build
Rspack 2.3 troca o parser JavaScript por SWC Next, adiciona cache experimental por loader e reduz pico de memória. O que muda no código, o que medir no CI e onde a migração quebra.
Ler artigo →
Desenvolvimento Polícia Civil de SP: 22 mil credenciais à venda por US$ 40 mil, Barracuda com root explorado e Nitori com 37,6 milhões
Grupo bl33dr00t põe 22 mil credenciais da Polícia Civil de SP à venda por US$ 40 mil enquanto a SSP nega invasão. Na mesma janela, a Barracuda confirma exploração de falhas que dão root em gateways ESG, a CISA corre contra o prazo de 13/11 e a Nitori expõe até 37,6 milhões de registros.
Ler artigo →