Skip to main content

Configure Dependabot grouped updates: one PR a month, CVEs instant

Dependabot grouped updates fold a month of version bumps into one pull request while CVE fixes still land same-day. The cooldown key most configs miss.

9 min read
Diagram of Dependabot running two independent lanes: version updates funnelled through cooldown and a monthly schedule into one grouped pull request, and security updates bypassing all of it to open immediately

TL;DR

A Dependabot grouped update is one pull request carrying every version bump for an ecosystem, produced by a groups: block — and it is the fix for a repository drowning in bot pull requests. Set interval: monthly with groups: { monthly-batch: { patterns: ["*"] } } and a cooldown of about seven days, and a year of version bumps collapses into twelve reviewable pull requests per ecosystem. Security fixes are untouched by all three keys: they run on a separate pipeline that ignores your schedule, your groups, and your open-PR limit.

What are Dependabot grouped updates — and why the default config floods you

The config that produces an unreadable pull request list usually looks like this, and it looks reasonable:

YAML
version: 2
updates:
- package-ecosystem: github-actions
  directory: "/"
  schedule:
    interval: daily
  open-pull-requests-limit: 10

Two keys are fighting each other. interval: daily tells Dependabot to check every day and open a pull request per dependency that moved. open-pull-requests-limit: 10 then caps how many of those can be open simultaneously. As GitHub’s Bruno Borges puts it in the post that prompted this one, “it caps the flood at 10 open pull requests, but it doesn’t stop the flood.”

That distinction is the whole article in one line. The limit is a queue depth, not a rate limit. Merge three, three more appear. The work never shrinks; it just arrives in a shape that makes the list look survivable.

The volume is real. Microsoft’s GCToolkit is a healthy, unexciting Java library, and 92 of its 578 commits — roughly one in six — were Dependabot version bumps, with 61 in the previous 12 months alone. That is a bump landing every six days on a repository nobody would describe as churny. At one pull request each, that is 61 review notifications, 61 CI runs, and 61 opportunities to develop the habit that actually costs you something: skimming the sender and closing the tab.

Which is the real failure mode. Alert fatigue is not a metaphor here — it is a trained response. Once the Dependabot label reads as ignorable, the one pull request that matters gets the same treatment as the other sixty. I wrote about the same dynamic hitting security triage queues flooded with AI-generated CVE reports: the damage is never the individual low-value item, it is what a high volume of them teaches the reviewer.

The rule everything else depends on: two lanes, not one

Before touching any config, internalize this, because every fear about slowing updates down dissolves once you do:

Dependabot version updates and Dependabot security updates are separate pipelines. schedule, groups, cooldown, and open-pull-requests-limit configure the first one. The second one ignores all four.

GitHub’s blog states it directly — “by default, the groups and schedule you set here shape your version updates, not your security fixes” — and the options reference backs each half of it independently: cooldown applies to version updates only, and security update pull requests “are not subject to this limit and do not count toward it” for open-pull-requests-limit.

So when an advisory with an available fix is published, the pull request is raised then. Not on the first of next month. Not after your seven-day cooldown. Then.

Dependabot's two independent lanes: a version-update lane where a published release passes through a seven-day cooldown, waits for the monthly schedule, and merges into a single grouped pull request; and a security lane where an advisory with a fix bypasses cooldown, schedule, groups, and the open-PR limit to raise a pull request immediately

Everything below is an edit to the top lane. The bottom lane has no knobs and needs none.

The config: one grouped pull request a month

Here is the replacement, straight from GitHub’s post:

YAML
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "monthly"
    groups:
      monthly-batch:
        patterns:
          - "*"

  - package-ecosystem: "maven"
    directory: "/"
    schedule:
      interval: "monthly"
    groups:
      monthly-batch:
        patterns:
          - "*"

Two changes, and the second is the one doing the work.

interval: "monthly" sets the cadence. On its own this is a modest improvement — you still get one pull request per dependency, just clustered onto one unpleasant day.

groups is the actual fix. A named group with patterns: ["*"] tells Dependabot to fold every matching dependency for that ecosystem into a single pull request. One branch, one CI run, one review, one merge. Applied to GCToolkit’s history, 61 individual bumps in a year become at most 12 pull requests per ecosystem — and a batch of nine minor bumps is genuinely faster to review than nine separate ones, because you read one changelog diff and run one test suite instead of context-switching nine times.

Note that groups lives per ecosystem, not globally. A repo with npm, Docker, and GitHub Actions gets three monthly pull requests, which is correct: those are three different blast radii and you want them reviewable in isolation.

Bar comparison of GCToolkit's dependency-bump volume: 92 of 578 total commits were Dependabot version bumps with 61 in the previous 12 months, shown as up to 61 individual pull requests under a daily schedule versus at most 12 grouped pull requests per ecosystem under a monthly schedule

The batch is only reviewable if CI can tell you whether it broke anything, which makes grouping a bet on your test suite. If the honest answer is “we’d merge it green either way,” fix that first — a testing strategy that actually gates merges is the prerequisite, not a follow-up.

Cooldown: the key most configs are still missing

Grouping fixes volume. It does nothing about a package that ships a broken release on Tuesday and yanks it on Wednesday — you just batch the breakage.

YAML
- package-ecosystem: "maven"
  directory: "/"
  schedule:
    interval: "monthly"
  cooldown:
    default-days: 7
  groups:
    monthly-batch:
      patterns:
        - "*"

cooldown makes Dependabot wait a set number of days after a version is published before proposing it. Seven days means you never adopt a release during the window when its first real-world bug reports are still coming in. default-days covers anything not matched by a more specific rule; GitHub’s reference documents 3 days as its fallback value, and the semver-aware keys — semver-major-days, semver-minor-days, semver-patch-days — let you hold majors for a month while patches move in days. include and exclude lists (up to 150 entries each, exclude winning ties) carve out the dependency you trust or the one you don’t.

This is the key that makes a slower cadence safer rather than merely quieter, and it costs you nothing on the security side, because cooldown applies to version updates only.

Monorepos: directories plus group-by

One package per repo is the easy case. In a monorepo, the plural key and one extra line matter:

YAML
- package-ecosystem: "npm"
  directories:
    - "/apps/*"
  schedule:
    interval: "monthly"
  groups:
    monthly-batch:
      group-by: dependency-name
      patterns:
        - "*"

directories (plural) takes globs, so /apps/* covers every workspace without an entry each. group-by: dependency-name then consolidates the same dependency across those directories into one pull request. Skip it and a single TypeScript bump across twelve apps arrives as twelve line items in your batch — technically grouped, practically still noise.

What each key actually controls

The reason most tuning attempts fail is that people reach for the knob that sits in the wrong lane. This is the whole surface:

Table mapping each dependabot.yml key to the pipeline it controls: schedule.interval, groups.patterns, cooldown and open-pull-requests-limit all apply to version updates only, while security updates are governed by none of them and are raised as soon as an advisory with a fix is published

Three mistakes follow from misreading that map:

Lowering open-pull-requests-limit to “reduce noise.” It reduces visible noise and nothing else. The default is five; the updates still queue behind it. If you want fewer pull requests, group them — if you want fewer updates, that is ignore, and you should be honest with yourself about whether you mean it.

Adding applies-to: security-updates to the monthly batch. Groups default to version updates for a reason. Bolt security onto the group you built to slow things down and you have batched your CVE response into a monthly window by hand. If you do want grouped security fixes — reasonable in a monorepo where one advisory touches twenty packages — declare a second group for it, with no cooldown.

Using ignore as a snooze button. ignore is permanent until removed, and it is invisible: nothing in the pull request list tells you a dependency has been silently frozen for eight months. Cooldown is the temporal tool; ignore is a decision you should be able to defend.

Side by side, the four levers people reach for are not interchangeable:

LeverWhat it actually changesWhat it costs youReach for it when
open-pull-requests-limitVisible queue depth, nothing elseNothing — and it fixes nothingNever, as a noise fix
ignoreDrops the update permanentlySilent version drift, invisible in the PR listYou have made a real compatibility decision
cooldownDelays adoption by N days after releaseA few days of lag on version updates onlyAlways — 7 days is a sane default
groups + interval: monthlyCollapses N pull requests into 1Batch review; needs CI you actually trustAlways

Only the bottom two rows reduce work. The top two rearrange it.

Why this is worth twenty minutes

The pattern generalizes past Dependabot. Every automated producer of engineering work — dependency bots, alerting, CI notifications — has a cadence knob and a batching knob, and teams reflexively reach for the cadence one because it is more obvious. Batching is almost always the better lever: it preserves the information while collapsing the interruption count, and interruption count is what actually degrades review quality. It is the same reasoning behind treating a CI pipeline as one program instead of a pile of independently-triggered jobs, and it belongs on the short list of config changes that pay back more than most tooling upgrades.

Open .github/dependabot.yml. If it says interval: daily and has no groups block, you are one commit away from a quieter repo — and, more to the point, from a Dependabot label your team still reads.

FAQ

Do Dependabot grouped updates delay security fixes?

No, and this is the load-bearing fact behind the whole config. Version updates and security updates are two separate pipelines: your schedule, your groups, and your cooldown shape version updates only. A security update is raised as soon as an advisory with an available fix is published, regardless of whether your interval says monthly.

What does open-pull-requests-limit actually do?

It caps how many version-update pull requests Dependabot keeps open at once — five by default — and raises no new ones until you merge or close some. It does not reduce how many updates exist, so the queue simply refills the moment you clear it. GitHub’s reference is explicit that security update pull requests are not subject to this limit and do not count toward it, so raising or lowering the number never affects your CVE response time either way.

How long should the Dependabot cooldown be?

Long enough to outlive a bad release, short enough to stay inside your monthly window — seven days is a reasonable default for most teams. If you want finer control, semver-major-days, semver-minor-days, and semver-patch-days let you hold majors for longer than patches. Cooldown applies to version updates only, so a longer window never slows a security fix.

How do I group Dependabot updates across a monorepo?

Use the plural directories key with a glob such as /apps/* instead of a single directory, then add group-by: dependency-name to the group. Without group-by, the same dependency bumping in twelve packages produces twelve separate entries; with it, one pull request updates that dependency everywhere it appears.

Can I group security updates too?

Yes, but you have to ask for it explicitly with applies-to: security-updates on a group, because groups default to version updates. Do it as a second group rather than by adding the key to your monthly batch — otherwise the security fixes inherit the batching you built to slow version bumps down, which is exactly the outcome the two-lane design exists to prevent.

Sources

Share this article:
X LinkedIn

Keep reading

Get new posts on AI, Claude Code & LLMs

New deep-dives on AI engineering, Claude Code, and developer tooling — follow along however you prefer.