yarn @nestjs/config 12.0.0

4 hours ago

What's Changed

@nestjs/config is now a native ES module, environment validation is built on Standard Schema instead of Joi-specific code, and the major version is aligned with the Nest 12 release line (there is no 5.x4.0.4 goes straight to 12.0.0).

ESM migration

The package is published as pure ESM ("type": "module", compiled with NodeNext) behind a proper exports map. The legacy root index.js / index.d.ts shims are gone, and deep imports into build internals are no longer resolvable — import from the package root.

// ✅
import { ConfigModule, ConfigService } from '@nestjs/config';

// ❌ no longer resolvable
import { ConfigService } from '@nestjs/config/dist/config.service';

require(esm) — CommonJS still works

You do not need to convert your app to ESM. Thanks to Node's require(esm) support (Node 20.19+ / 22.12+), a CommonJS app can keep using require('@nestjs/config') unchanged.

Validation is now Standard Schema based

validationSchema accepts any schema implementing the Standard Schema spec — Zod (v3, v4, v4-mini), Valibot, ArkType, Joi 18+, and anything else that adopts it. There is no longer any Joi-specific code path in the module, and Joi is no longer implied as the validation library.

ConfigModule.forRoot({
  validationSchema: z.object({
    PORT: z.coerce.number().default(3000),
    DATABASE_NAME: z.string(),
  }),
});

Joi keeps working — it implements Standard Schema as of v18 — and the historical abortEarly: false / allowUnknown: true defaults are still applied automatically for Joi schemas, so existing Joi setups behave as before.

Breaking: validationOptions shape

Options are now the Standard Schema Options object, and library-specific settings move under libraryOptions:

// Before (4.x)
validationOptions: { allowUnknown: false, abortEarly: true }

// Now (12.x)
validationOptions: { libraryOptions: { allowUnknown: false, abortEarly: true } }

The generic parameter changed accordingly: ConfigModuleOptions<ValidationOptions extends StandardSchemaV1.Options>, and validationSchema is typed as StandardSchemaV1 rather than any — a schema that does not implement the spec is now a compile-time error instead of a runtime one.

Breaking: validation error format

Issues are formatted by this package rather than by the schema library. Each issue is rendered as path: message and issues are newline-separated:

Config validation error: PORT: "PORT" is required
DATABASE_NAME: "DATABASE_NAME" is required

Anything asserting on the old single-line Joi message string needs updating.

Object schemas no longer strip your environment

Schemas like Zod's z.object() drop undeclared keys. Those variables are now merged back into the validated result, so unrelated variables stay reachable through both process.env and ConfigService instead of disappearing after validation.

Breaking: peer dependencies

@nestjs/common is now ^11.0.0 || ^12.0.0. Nest 10 is no longer supported — stay on @nestjs/config@4 if you are still on Nest 10.

Breaking: lodash replaced with es-toolkit

The lodash runtime dependency is gone, replaced by es-toolkit. This is transparent unless you relied on the transitive lodash install.

Breaking: stricter ConfigService.get() inference

The explicit-type parameter on get() / getOrThrow() is now constrained to the value at the given path (R extends PathValue<T, P>), fixing the long-standing bug where an unrelated type could be asserted for a key. Call sites that passed a type inconsistent with the config shape will now fail to compile — that mismatch was always a latent bug.

New: override

Values from .env files can now take precedence over pre-existing process.env variables:

ConfigModule.forRoot({ override: true });

Default remains false — the existing "process.env wins" behavior.

New: custom parser

.env files no longer have to be dotenv-formatted. Supply any function that turns a Buffer into an object — YAML, TOML, JSON, whatever:

ConfigModule.forRoot({
  parser: (buffer) => YAML.parse(buffer.toString()),
});

The parser is used both at bootstrap and for variable re-interpolation inside ConfigService.

Other changes

  • Tests migrated from Jest to Vitest; linting migrated from ESLint to oxlint.
  • dotenv 17.4.2, dotenv-expand 13.
  • Fixed a typo in the ConditionalModule timeout error message ("Bause" → "Because").

Don't miss a new config release

NewReleases is sending notifications on new releases.