# Configuring minimum release age across npm, pnpm, and yarn

> Source: <https://gist.github.com/mcollina/b294a6c39ee700d24073c0e5a4e93104>
> Published: 2026-04-30 09:41:24+00:00

# Configuring minimum release age across npm, pnpm, and yarn

Setting a minimum release age (a "cooldown") on dependencies is a cheap, high-leverage defense against supply-chain attacks. Most malicious package versions are detected and yanked within hours, so a 24-hour delay filters out the smash-and-grab incidents (axios 1.14.1, ua-parser-js, Solana web3.js, etc.).

All three major Node.js package managers now support this, but each one used a different name and a different unit. Here is what you need.

## Minimum versions

| Tool   | Setting                | Unit                     | Introduced in           |
|--------|------------------------|--------------------------|-------------------------|
| npm    | `min-release-age`      | days                     | npm CLI **11.10.0** (Feb 2026) |
| pnpm   | `minimumReleaseAge`    | minutes                  | pnpm **10.16** (Sep 2025); default `1440` since pnpm **11.0** |
| Yarn   | `npmMinimalAgeGate`    | minutes (numeric)        | Yarn Berry **4.10.0**   |

A note on Yarn: the docs advertise duration strings like `"7d"`, but there's a known parsing bug (yarnpkg/berry#6991) where day suffixes were silently ignored. Until that's resolved everywhere, pass minutes as a number. 1 day = `1440`.

## npm — per-project

Add to `.npmrc` in the project root:

```ini
min-release-age=1
```

The value is in days. Do not combine with `--before` in the same invocation — npm errors out if both are present.

## npm — locally (user-wide)

```bash
npm config set min-release-age 1 --location=user
```

This writes to `~/.npmrc`. Use `--location=global` if you want it in the global npm config instead.

## pnpm — per-project

Put it in `pnpm-workspace.yaml` (this is the canonical place since pnpm 11; in earlier versions `.npmrc` also works):

```yaml
minimumReleaseAge: 1440
```

Optional, if you have internal packages you want to bypass the gate:

```yaml
minimumReleaseAge: 1440
minimumReleaseAgeExclude:
  - '@platformatic/*'
```

If you're still on pnpm 10.x, the `.npmrc` form is:

```ini
minimum-release-age=1440
```

Heads-up: on pnpm 10.x there's a known bug where `minimumReleaseAge` is silently ignored if any package in the workspace has `shared-workspace-lockfile=false` in its `.npmrc` (pnpm/pnpm#10008). Worth checking.

## pnpm — locally (user-wide)

```bash
pnpm config set minimumReleaseAge 1440 --location=user
```

On pnpm 11+, non-auth settings like this go into `~/.config/pnpm/config.yaml` rather than `~/.npmrc`.

## Yarn (Berry 4.10+) — per-project

In `.yarnrc.yml`:

```yaml
npmMinimalAgeGate: 1440
```

If you have packages that must bypass the gate:

```yaml
npmMinimalAgeGate: 1440
npmPreapprovedPackages:
  - "@platformatic/*"
```

`npmPreapprovedPackages` accepts both glob patterns and exact locators (e.g. `@aws-sdk/types@3.877.0`), which is more flexible than pnpm's package-name-only exclusions.

## Yarn — locally (user-wide)

```bash
yarn config set --home npmMinimalAgeGate 1440
```

`--home` writes to `~/.yarnrc.yml` instead of the project-local file.

## A few caveats worth knowing

The cooldown is enforced at install time, not at update-suggestion time. If you're using Renovate or Dependabot, configure their `minimumReleaseAge` / `cooldown` independently — otherwise they'll keep opening PRs you can't actually install. Renovate 42's `config:best-practices` preset already sets a 3-day default for npm; Dependabot's `cooldown.default-days` is the equivalent.

None of these tools currently let you scope the gate per registry, so internal packages from a private registry get held back along with everything else unless you put them in the exclusion list (npm doesn't have one yet — there's an open issue, #8994).

The defaults will likely shift soon: pnpm 11 already turned this on by default at 1440 minutes, and npm CLI v12 is expected to do the same. Setting it explicitly now means your config keeps working unchanged when defaults move.
