O NestJS 12 foi lançado oficialmente em 27 de agosto de 2026 e é uma das atualizações mais profundas da história do framework — mas, curiosamente, uma das que menos exige reescrita de código de aplicação.
A versão gira em torno de quatro frentes: pacotes ESM, suporte de primeira classe a Standard Schema para validação e serialização, uma CLI reconstruída do zero e observabilidade nativa através do novo pacote @nestjs/observe.
E há um ponto importante logo de saída: aplicações CommonJS continuam funcionando. Migrar o seu próprio código para ESM é totalmente opcional.
Entre os destaques estão:
- Todos os pacotes do core agora são ESM, com CommonJS continuando a funcionar via
require(esm); - Standard Schema nos decorators de rota, permitindo Zod, Valibot e ArkType no
@Body(),@Query()e@Param(); - Serialização por schema com o novo
StandardSchemaSerializerInterceptor; - Observabilidade nativa com o SDK
@nestjs/observe; - CLI reconstruída, com os novos comandos
nest upgradeenest deploy; - Rspack no lugar do webpack, oxlint no lugar do ESLint e Vitest como padrão em projetos ESM;
- Diagnóstico de conflito de rotas, para identificar rotas sombreadas ou duplicadas;
- Códigos de erro legíveis por máquina nas exceções HTTP;
- Logs estruturados por padrão no
ConsoleLogger; - Node.js v20.19+ ou v22.12+ como requisito mínimo.
Vamos entender o que muda na prática.
Os pacotes do NestJS agora são ESM
A mudança arquitetural mais importante do NestJS 12 é a migração dos pacotes do core de CommonJS para ESM.
Essa discussão já vinha se arrastando no ecossistema Node.js há anos, e o motivo de ela finalmente ter destravado é técnico: o suporte a require(esm) nas versões modernas do Node.js.
Na prática, isso significa que um projeto CommonJS consegue continuar carregando pacotes que são ESM, sem precisar reescrever imports, converter arquivos ou mudar a estratégia de build.
Por isso a recomendação oficial é direta: na maioria dos projetos, nada precisa ser feito.
Ainda assim, vale revisar três pontos que costumam assumir CommonJS de forma implícita:
- Scripts customizados de bootstrap da aplicação;
- Ferramentas e configurações de build;
- Test runners e mocks que dependem do formato dos módulos.
Também é um bom momento para eliminar deep imports — aqueles imports que alcançam caminhos internos dos pacotes do Nest em vez de usar a API pública. Eles sempre foram frágeis, e continuam sendo o tipo de coisa que quebra em uma troca de formato de módulo.
Outra mudança visível está na criação de projetos. O comando:
nest new
agora pergunta se você quer gerar um projeto CommonJS ou ESM. A escolha define também o restante da toolchain, como veremos adiante.
Validação com Standard Schema direto nos decorators
Se você acompanha o ecossistema TypeScript, provavelmente já cruzou com o Standard Schema: uma especificação comum que bibliotecas de validação implementam para poderem ser usadas de forma intercambiável.
O NestJS 12 adota essa especificação de forma nativa.
Os decorators de parâmetro de rota — @Body(), @Query(), @Param() e @RawBody() — passam a aceitar uma nova opção schema, pensada para bibliotecas compatíveis como Zod, Valibot e ArkType:
@Post()
create(@Body({ schema: createUserSchema }) body: CreateUserDto) {
return this.usersService.create(body);
}
@Get(':id')
findOne(@Param('id', { schema: z.coerce.number().int().positive() }) id: number) {
return this.usersService.findOne(id);
}
Há um detalhe de implementação que vale entender bem: o decorator apenas anexa o metadado. Ele não valida nada sozinho.
Quem valida é o novo pipe, que precisa ser registrado:
app.useGlobalPipes(new StandardSchemaValidationPipe());
Isso mantém a arquitetura do framework coerente com o que já existia: o decorator descreve a intenção, o pipe executa.
Um ganho importante é que os mesmos schemas alimentam a geração de OpenAPI. Ou seja, você não precisa manter uma definição para validar e outra para documentar.
E, para quem já tem uma base grande escrita no modelo tradicional, a mensagem é tranquilizadora: o fluxo com class-validator continua totalmente suportado, sem qualquer plano de remoção.
Serialização também ganhou uma versão Standard Schema
A mesma ideia foi levada para o caminho de saída da requisição.
O novo StandardSchemaSerializerInterceptor valida e transforma a resposta usando o mesmo ecossistema de schemas:
@UseInterceptors(StandardSchemaSerializerInterceptor)
@SerializeOptions({ schema: userResponseSchema })
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(id);
}
Isso resolve um problema bastante concreto de APIs em produção: garantir que o objeto devolvido ao cliente contenha exatamente os campos previstos — e não aquilo que acidentalmente veio do banco de dados.
A escolha entre as duas abordagens é por caso de uso:
- ValidationPipe e ClassSerializerInterceptor para DTOs baseados em classes;
- Versões Standard Schema quando os seus schemas já existem no projeto.
Observabilidade nativa com @nestjs/observe
Talvez a novidade mais estratégica do NestJS 12 seja o @nestjs/observe, o SDK oficial de observabilidade do framework.
A diferença em relação a um APM genérico está na abordagem. Em vez de instrumentar o servidor HTTP por fora, o SDK se conecta ao próprio ciclo de vida de requisição do Nest, através de uma nova opção da aplicação chamada instrument:
export const { ObserveModule, ObserveInstrument } = createObserveModule();
const app = await NestFactory.create(AppModule, {
instrument: ObserveInstrument,
});
A consequência prática é que os dados chegam descritos nos termos da sua aplicação: controllers, providers, resolvers e consumidores de fila — e não em termos de rotas HTTP genéricas.
A instrumentação automática cobre:
- HTTP;
- GraphQL;
- gRPC;
- Transportes de microservices;
- Consumidores de fila;
- Execuções de cron.
Sem instrumentação manual de spans e sem precisar rodar um collector.
É um recurso opt-in e novo, ou seja: não há nada para migrar. Tanto o nest new quanto o nest upgrade conseguem fazer a configuração inicial com a flag --observe.
O @nestjs/config agora valida por Standard Schema
O módulo de configuração deixou de ser acoplado ao Joi.
A opção validationSchema passa a aceitar qualquer schema compatível com Standard Schema:
ConfigModule.forRoot({
validationSchema: z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
PORT: z.coerce.number().default(3000),
}),
});
Quem já usa Joi não precisa reescrever nada, mas precisa observar dois pontos:
- Atualizar para o Joi v18+, que é a primeira versão a implementar Standard Schema;
- Mover as configurações específicas da biblioteca para dentro de
validationOptions.libraryOptions.
Diagnóstico de conflito de rotas
Esse é o tipo de recurso que só faz sentido para quem já perdeu tempo com o problema.
As rotas do Nest são registradas na ordem de declaração. Em adaptadores sensíveis a ordem, isso significa que uma rota como:
@Get(':id')
pode silenciosamente sombrear uma rota declarada depois:
@Get('me')
O resultado é uma requisição para /users/me chegando no handler de /users/:id com o id valendo a string "me". Nenhum erro, nenhum aviso — só um comportamento errado.
O NestJS 12 traz duas opções opt-in para expor esse cenário:
const app = await NestFactory.create(AppModule, {
routeConflictPolicy: { duplicate: 'error', shadow: 'warn' },
routeResolutionStrategy: 'specificity',
});
As duas mantêm o comportamento anterior por padrão, então nada muda a menos que você as configure explicitamente.
Códigos de erro legíveis por máquina
Outra melhoria pequena no tamanho e grande no impacto do dia a dia.
O HttpExceptionOptions passa a aceitar um errorCode, que é serializado no corpo da resposta:
throw new BadRequestException('Password is too weak', { errorCode: 'WEAK_PASSWORD' });
Com isso, o cliente pode ramificar a lógica em cima de um identificador estável, em vez de fazer comparação de string na mensagem de erro — que muda quando alguém corrige uma vírgula ou traduz o texto.
Logs estruturados no ConsoleLogger
O ConsoleLogger agora trata objetos passados depois da mensagem como parâmetros estruturados do mesmo registro, e não como registros separados:
logger.log('User created', { userId: 1, email: '[email protected]' });
No modo JSON, esses dados ficam aninhados sob params, ou podem ser espalhados na raiz com flattenParams.
O comportamento vem ligado por padrão. Para voltar ao formato anterior, basta configurar structuredParams: false.
A CLI do NestJS foi reconstruída
A @nestjs/cli v12 não recebeu apenas comandos novos: ela foi reescrita.
O código-fonte inteiro migrou para ESM, os testes saíram do Jest para o Vitest, foram adicionados testes end-to-end para todos os comandos, e as classes de comando passaram a receber objetos de contexto tipados em vez de entradas e arrays de opções sem tipo.
Novos comandos
nest upgrade(aliasupdate) — atualiza um projeto v11 para v12 e aplica as etapas mecânicas da migração;nest deploy— publica a aplicação na nuvem via Mau, instalando o@nestjs/mauno primeiro uso.
Novos padrões de toolchain
- Rspack passa a ser o bundler padrão para monorepos. As flags
--webpacke--webpackPath(e suas equivalentes nonest-cli.json) estão depreciadas em favor de--builder rspack; - oxlint substitui o ESLint nos projetos gerados;
- Vitest é o test runner padrão em projetos ESM; projetos CommonJS continuam com Jest;
- bun passa a ser um gerenciador de pacotes suportado, ao lado de npm, yarn e pnpm;
- O schematic
decoratorpassa a gerar decorators no formato preferidoReflector.createDecorator(), e o schematicangularfoi removido.
Novas opções
nest buildenest start:--rspackPath [path],--emit-declarations(SWC),--no-type-checke--silent;nest build:--parallel [concurrency], para compilar projetos de um monorepo em paralelo junto com--all;nest-cli.json:includeLibraryAssets, para copiar assets de libraries para o build da aplicação.
Novidades espalhadas pelo restante do framework
Além dos destaques principais, o NestJS 12 traz uma série de melhorias menores que resolvem incômodos bem específicos:
- Formato de erro do ValidationPipe — uma nova opção controla o formato das respostas de erro de validação;
- Filtro de exceção para gRPC — o
GrpcExceptionFiltere exceções específicas por status mapeiam erros para os status corretos do gRPC, em vez de devolverUNKNOWN; - Padrões Kafka por expressão regular —
@MessagePattern()e@EventPattern()aceitam umRegExpno transporte Kafka; - Gateways WebSocket com escopo de requisição — gateways passam a suportar providers request-scoped, com o socket injetável pelo token
REQUEST; - Motivo do disconnect — o
handleDisconnectpode receber o motivo da desconexão; - Hook pré-requisição em microservices — um novo hook roda antes do handler da mensagem ser invocado;
- Shutdown gracioso no Express — o adaptador drena as requisições em andamento ao desligar;
- Mapeamento de erros dos adaptadores HTTP — retrabalhado no core, no Express e no Fastify.
O shutdown gracioso do Express, em particular, é uma daquelas correções que quem roda Kubernetes agradece: durante um rollout, requisições em andamento deixam de ser cortadas no meio.
O que quebra ao subir para o NestJS 12
A equipe optou por concentrar as mudanças incompatíveis fora do código de aplicação. Ainda assim, vale conhecer a lista:
- Node.js v20.19+ ou v22.12+ — a linha 21.x não é suportada, e o comando de upgrade se recusa a rodar em versões anteriores;
- Pacotes em ESM — normalmente nada muda, graças ao
require(esm); revise bootstrap, bundler e test runner customizados; - Hooks de ciclo de vida — agora são invocados por nível de hierarquia dos componentes; revise suposições de ordem entre providers e módulos relacionados;
- NATS v3 — o pacote
natsfoi substituído por@nats-io/transport-node; as mensagens passam a ser serializadas como JSON e deserializers customizados recebem a mensagem completa, lida commsg.json(); - GraphQL subscriptions — o suporte a
subscriptions-transport-wsfoi removido em favor dographql-ws; os protocolos são incompatíveis no fio, então os clientes precisam ser atualizados; - GraphiQL passa a ser a IDE padrão de GraphQL — troque
playgroundporgraphiql; - @nestjs/config — validação via Standard Schema, com Joi v18+ e
validationOptions.libraryOptions; - Assinaturas de pipes — refinadas, com
ArgumentMetadataagora genérico; ajuste pipes customizados se o compilador reclamar; - ConsoleLogger com params estruturados ligado por padrão;
- Fluxos com webpack na CLI depreciados, em favor de
--builder rspack; - Schematic
angularremovido.
A boa notícia é que a maior parte disso é tratada automaticamente pelo nest upgrade.
Como atualizar para o NestJS 12
O primeiro passo é atualizar a CLI, já que é ela que carrega o comando de upgrade:
npm i -g @nestjs/cli@latest
Depois, a partir da raiz do projeto:
nest upgrade
O comando move todos os pacotes @nestjs/* para a major compatível com a v12 de uma vez só e aplica as partes mecânicas da migração:
- Opções de webpack no
nest-cli.json; - Renomeação de
playgroundparagraphiqlno GraphQL e troca do transporte de subscriptions; - Substituição do pacote do NATS;
- Opções de validação do
@nestjs/config; - Atualizações de Jest e Joi.
Ao final, ele imprime um relatório com tudo o que alterou e tudo o que ainda precisa de revisão manual.
Antes de aplicar em um projeto real, vale executar:
nest upgrade --dry-run
para ver esse mesmo relatório sem que nenhum arquivo seja tocado.
E um ponto importante: o comando deliberadamente não migra o seu projeto para ESM, Vitest ou oxlint. Esses são os padrões de projetos novos — projetos existentes adotam no próprio ritmo.
Como em qualquer atualização de major, o roteiro seguro continua o mesmo:
- Rodar toda a suíte de testes automatizados;
- Validar autenticação, guards, interceptors e pipes customizados;
- Conferir microservices, filas e jobs agendados;
- Testar o processo de build e o deploy em um ambiente de staging antes da produção.
Vale a pena atualizar para o NestJS 12?
Para projetos que já estão no NestJS 11, a atualização é bem menos arriscada do que o número da major sugere — justamente porque as mudanças mais radicais acontecem em camadas que a aplicação normalmente não toca.
O que você ganha só por subir de versão:
- Shutdown gracioso no Express;
- Mapeamento correto de erros nos adaptadores HTTP;
- Status adequados nas exceções de gRPC;
- Logs estruturados no
ConsoleLogger.
O que é adoção opcional, e pode entrar depois com calma:
- Migrar o projeto para ESM;
- Trocar class-validator por Zod, Valibot ou ArkType;
- Adotar Vitest, oxlint e Rspack;
- Ligar o
@nestjs/observe.
O principal bloqueio prático não é o framework, e sim o runtime: se o seu ambiente ainda roda uma versão de Node.js anterior à v20.19, essa é a primeira coisa a resolver.
O que o NestJS 12 mostra sobre a direção do framework
Olhando o conjunto, o NestJS 12 tem uma linha bastante clara.
De um lado, o framework está se alinhando ao ecossistema em vez de manter soluções próprias: ESM em vez de CommonJS, Standard Schema em vez de acoplamento a uma biblioteca de validação específica, graphql-ws em vez de um transporte legado.
De outro, está modernizando a toolchain com implementações nativas de alto desempenho — Rspack e oxlint seguem exatamente a mesma tendência que o Turbopack representa no mundo Next.js.
E há uma terceira frente, mais silenciosa: várias novidades desta versão existem para tornar o comportamento do sistema observável. Conflito de rotas que deixa de ser invisível. Código de erro que o cliente consegue interpretar. Log que vira dado estruturado. Observabilidade que fala a linguagem dos seus controllers.
São melhorias menos vistosas do que uma API nova, mas que atacam justamente o tipo de problema que costuma custar caro em produção.
Perguntas frequentes sobre o NestJS 12
Quando o NestJS 12 foi lançado?
O NestJS 12.0.0 foi lançado oficialmente em 27 de agosto de 2026.
O que há de novo no NestJS 12?
As principais novidades são os pacotes em ESM, o suporte de primeira classe a Standard Schema para validação e serialização, a CLI reconstruída com os comandos nest upgrade e nest deploy, e a observabilidade nativa através do SDK @nestjs/observe.
Preciso migrar minha aplicação para ESM no NestJS 12?
Não. Os pacotes do Nest passaram a ser ESM, mas aplicações CommonJS continuam funcionando graças ao require(esm) das versões modernas do Node.js. Migrar o seu próprio código é opcional.
Qual a versão mínima do Node.js para o NestJS 12?
É necessário Node.js v20.19+ ou v22.12+. A linha 21.x não é suportada, e o comando nest upgrade se recusa a rodar em versões anteriores. A recomendação é usar a LTS ativa mais recente.
O class-validator vai ser removido do NestJS?
Não. O suporte a Standard Schema é uma alternativa, não uma substituição. O fluxo baseado em decorators com class-validator continua totalmente suportado, sem plano de remoção.
Como atualizar um projeto do NestJS 11 para o 12?
Atualize a CLI com npm i -g @nestjs/cli@latest e execute nest upgrade na raiz do projeto. Rode antes com --dry-run para ver o relatório do que seria alterado sem tocar nos arquivos.
O NestJS 12 obriga a usar Vitest e oxlint?
Não. Vitest, oxlint e ESM são os padrões apenas para projetos novos gerados pela CLI. O nest upgrade não converte projetos existentes para eles.
O que é o @nestjs/observe?
É o SDK oficial de observabilidade do NestJS. Ele se conecta ao ciclo de vida de requisição do próprio framework pela opção instrument, e instrumenta automaticamente HTTP, GraphQL, gRPC, transportes de microservices, consumidores de fila e execuções de cron — sem instrumentação manual de spans e sem collector.