What does Bundler 4's `cooldown` setting do during resolution, and why does it never downgrade a version already pinned in Gemfile.lock?
answer
- age before adoption, in days
- --cooldown N beats BUNDLE_COOLDOWN beats source
- --cooldown 0 bypasses for one run
- needs created_at from the gem server
- locked versions stay; named update gems don't
basics
~20 scooldown makes Bundler ignore gem versions published fewer than N days ago when it resolves. It governs adopting new versions only, so versions already in Gemfile.lock stay usable, except for gems you explicitly name on bundle update.
solid answer
~40 sAdded in Bundler 4.0.13, `cooldown` sets how many days a published gem version must age before Bundler will resolve to it, so a freshly pushed release - possibly a compromised one - is not adopted the day it appears. It comes from three layers: `--cooldown N` on `install`, `update`, `add` and `outdated` wins over `bundle config set cooldown N` or `BUNDLE_COOLDOWN`, which wins over a per-source `cooldown:` keyword in the Gemfile; `--cooldown 0` bypasses it for one run. Filtering needs the server's per-version `created_at` timestamp; versions without it stay resolvable. Versions already in the lockfile are never retracted, because unrelated operations would otherwise fail; gems named on `bundle update GEM` are the exception and stay subject to the window.
code
bash · 5 lines# wait 7 days before adopting any new gem version
bundle config set cooldown 7
# urgent fix: bypass the window for one run, move only rack
bundle update rack --cooldown 0 --conservativego deeper
Recall that Bundler can be told to wait a number of days before using newly published gem versions, and that it is off unless configured.
Explain the three layers and their precedence, what --cooldown 0 does, and why the filter depends on created_at metadata from the server.
Explain why locked versions are exempt while named update gems are not, and how to push an urgent security fix through the window with minimal churn.
Choose a cooldown length that balances exposure to compromised releases against delay in getting fixes, and decide which registries are exempt.
## What cooldown is for When a gem server publishes a new release, a resolver that always prefers the newest allowed version picks it up on the next `bundle update`. That is usually what you want - but if the release is malicious or broken, the first projects to adopt it are the ones hurt. A **cooldown** is a waiting period: Bundler will not resolve to a version until it has been public for a number of days, giving the community time to notice and yank a bad release. Bundler added the `cooldown` setting in **4.0.13**. It is **unset by default**, meaning no waiting period. ## Where the value comes from The effective cooldown for a gem is chosen from three layers, highest precedence first: 1. The CLI flag `--cooldown N` on `bundle install`, `update`, `add` and `outdated` (and on `bundle lock`). 2. The Bundler setting: `bundle config set cooldown N` or the environment variable `BUNDLE_COOLDOWN=N`. 3. The per-source keyword in the Gemfile: `source "https://rubygems.org", cooldown: 7`. The CLI flag and the setting apply to **every** source, including ones declared with their own `cooldown:`. To keep a private registry exempt while cooling public gems, declare that source with `cooldown: 0`; a `--cooldown N` on the command line still overrides it for that run. Passing `--cooldown 0` disables the window for one run. ## How the filter works - During resolution Bundler drops candidate versions whose publish time is within the window. - The publish time comes from a per-version **`created_at`** timestamp in the gem server's v2 compact-index responses. - Versions **without** that metadata - older servers, historical entries, registries that still emit the v1 format - are treated as outside the window and stay resolvable. If you rely on cooldown for supply-chain protection, confirm your server emits `created_at`. - When the window blocks the only matching versions, the resolution error adds a hint: "N versions excluded by the cooldown setting; pass `--cooldown 0` to bypass". - Since 4.0.19 Bundler also prints a summary of cooldown-skipped versions at the end of `install`, `update` and `lock`. ## Why locked versions are never retracted Bundler's resolver treats a version already written to Gemfile.lock as **adopted**. Cooldown only governs the adoption of *new* versions, so it never filters out a locked one. Without that rule, any unrelated operation - adding a gem, a conservative re-resolve after a Gemfile edit - could become impossible whenever the only version matching a requirement is the locked one and it is still younger than the window. The exception is a gem you **name** on `bundle update GEM`. You asked to move it, so it stays subject to cooldown: a locked version that is still inside the window is pushed back to an older one, or the command fails loudly when no older version fits. ## Cooldown in practice | Situation | What to run | |---|---| | team-wide default | `bundle config set cooldown 7` or `BUNDLE_COOLDOWN=7` in CI | | internal registry exempt | `source "https://internal.example", cooldown: 0` in the Gemfile | | urgent security release inside the window | `bundle update rack --cooldown 0 --conservative` | The `bundle update` man page recommends combining `--cooldown 0` with `--conservative` when bypassing the window for an urgent update, so only the named gem moves and no fresh transitive versions sneak in. ## What cooldown does not do - It does not change what an unchanged Gemfile.lock installs: `bundle install` from a committed lockfile resolves nothing, so there is nothing to filter. - It does not verify package contents. That is the job of the lockfile's `CHECKSUMS` section; cooldown only delays adoption. - It does not protect gems whose server omits `created_at`, as described above. - It does not replace review: a release older than the window can still be bad, and the lockfile diff remains the place where a version change is accepted. Treat it as one layer beside checksums and frozen installs, not a replacement for either.
- CI sets `BUNDLE_COOLDOWN=7`, but the Gemfile declares the public source with `cooldown: 14`. Which applies?Seven days. The Bundler setting, whether from `bundle config` or `BUNDLE_COOLDOWN`, outranks the per-source keyword and applies uniformly to every source. Only a `--cooldown N` flag on the command line would override it for that run.
- Why can cooldown silently fail to protect you on a private gem server?Filtering depends on the per-version `created_at` timestamp in the v2 compact-index format. A server that emits only the v1 format, or lacks that metadata, makes every version look outside the window, so all of them stay resolvable with no warning that the filter did nothing.
saying these in an interview costs you the question
- Cooldown downgrades any locked gem younger than the window
- The Gemfile's per-source cooldown overrides BUNDLE_COOLDOWN
- Versions without created_at metadata are blocked by cooldown
- Cooldown verifies gem contents like CHECKSUMS does
- Cooldown is on by default in Bundler 4