Turn on Dependabot or Renovate for the first time on any repo with a real dependency tree and the outcome is predictable: forty pull requests by morning, most of them patch bumps to transitive dependencies nobody’s ever heard of. The tool did exactly what it was told, which is the problem — “open a PR for every new version of everything” is technically automated dependency management, but it’s not usably automated dependency management. The gap between those two is entirely configuration, and it’s worth closing before turning this on for a team, not after the first round of complaints.

Both tools solve the same underlying problem and both are viable; Dependabot is built into GitHub and requires no external service, Renovate is more configurable and runs the same way across GitHub, GitLab, and Bitbucket. The patterns below apply to both, with syntax differences noted.

Grouping: One PR, Not Fifteen

The single highest-leverage setting is grouping related updates into one PR instead of one-per-package. Nobody wants to review fifteen separate PRs bumping every @types/* package by a patch version in the same week.

Renovate (renovate.json):

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": ["config:recommended"],
  "packageRules": [
    {
      "matchPackagePatterns": ["^@types/"],
      "groupName": "type definitions"
    },
    {
      "matchPackagePatterns": ["^eslint", "^@typescript-eslint/"],
      "groupName": "linting"
    },
    {
      "matchUpdateTypes": ["patch", "pin", "digest"],
      "groupName": "patch and digest updates",
      "automerge": true
    }
  ]
}

Dependabot (.github/dependabot.yml) added grouping later than Renovate and it’s coarser, but it covers the common case:

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    groups:
      dev-dependencies:
        dependency-type: "development"
      production-minor-patch:
        applies-to: "version-updates"
        update-types: ["minor", "patch"]

The effect is the same either way: instead of forty PRs, a Monday morning yields maybe three or four groups, each with a diff that’s actually reviewable in one pass.

Schedules

Both tools default to opening PRs as soon as a new version is detected, which means notifications trickle in at random times all week. A schedule batches everything into a predictable window instead: in Renovate, a top-level "schedule": ["before 6am on monday"] plus a "timezone" field; in Dependabot’s dependabot.yml, the equivalent is an interval: "weekly" block under schedule with an explicit day, time, and timezone. Both accept human-readable cron-like strings rather than requiring raw cron syntax, which makes the config self-documenting for anyone reading it later without having to decode 0 5 * * 1.

For a small team, weekly is usually the right cadence — daily creates review fatigue, monthly lets vulnerable versions sit around too long. Security patches are the exception on both tools: Dependabot and Renovate both raise vulnerability-driven PRs immediately regardless of the configured schedule, which is the correct override.

Automerge for Patch Updates — With Guardrails

Automerging is where teams either save real review time or automate their way into a broken build, and the difference is entirely about what gate stands between “PR opened” and “PR merged.”

{
  "packageRules": [
    {
      "matchUpdateTypes": ["patch"],
      "automerge": true,
      "automergeType": "pr",
      "platformAutomerge": true
    }
  ]
}

automergeType: "pr" (rather than the more aggressive branch, which skips opening a PR at all) still opens a PR, still runs CI against it, and only merges once every required status check passes — the automation is “skip the human click,” not “skip the tests.” That distinction matters: automerge should never mean bypassing CI, only bypassing the human who’d otherwise click the merge button on a green PR they weren’t going to meaningfully review anyway.

None of this works without a branch protection rule on the repo requiring those status checks (test, build, lint, whatever your pipeline runs) to pass before merge is even possible. Renovate’s and Dependabot’s automerge settings are a request to merge, not an override of GitHub’s own merge rules — without a required-checks rule in place, a red PR from either bot has nothing stopping it from merging anyway, which defeats the entire point of gating automerge on CI in the first place. Set that rule once at the repo level and every automerge config downstream of it inherits the protection for free.

Minor and major version bumps are a different risk profile and generally shouldn’t automerge — a minor semver bump can still break behavior in practice even when it’s not supposed to, and a major bump is explicitly expected to. Those should land as PRs for a human to actually read the changelog on.

Lockfile Maintenance

Even with no direct dependency changes, transitive dependencies drift over time, and periodically refreshing the lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml) keeps builds reproducible against currently-available versions rather than versions that might get yanked.

{
  "lockFileMaintenance": {
    "enabled": true,
    "schedule": ["before 6am on the first day of the month"]
  }
}

Dependabot doesn’t have a direct lockfile-maintenance equivalent — it only opens PRs for direct dependency updates that have new versions, so the same effect requires either a scheduled workflow running npm update and committing the result, or accepting that lockfile drift only gets addressed incidentally as direct dependencies update.

Docker Image Digest Pinning

Tagging a base image node:20 or even node:20.11 is not actually pinned — the same tag can point to a different image tomorrow if the maintainer republishes it, and that’s a real supply-chain and reproducibility gap. Pinning by digest fixes the image content exactly:

# Before: mutable tag, silently changes underneath you
FROM node:20-alpine

# After: pinned to an exact content hash
FROM node:20-alpine@sha256:c13b26e7e42c7e7e6a2f9a0c88e0a6bcf3e5c0e5a3f2d3b1a9e8f7c6d5b4a3e2

The obvious downside of digest pinning by hand is that nobody updates it, ever, because nobody remembers to and the digest is unreadable. This is exactly the case Renovate handles well — a packageRules entry matching matchDatasources: ["docker"] and matchUpdateTypes: ["digest"] resolves the current digest for a given tag and opens a PR whenever the upstream image is rebuilt, so the base image still gets patched, just explicitly and reviewably instead of silently. Pairing that rule with automerge: true is usually safe, since a digest-only update by definition doesn’t change the tag your Dockerfile pins to visually — it only changes what that tag currently resolves to, and CI still runs against the new digest before merge either way.

Dependabot supports Docker digest updates too, via the docker ecosystem entry in dependabot.yml, though its diffing is generally less granular about separating tag bumps from pure digest refreshes.

GitHub Actions Pinning

The same problem exists for GitHub Actions: uses: actions/checkout@v4 is a floating tag that the action’s maintainer (or, in a supply-chain attack, someone who compromised their account) can repoint at any time. Pinning to a commit SHA closes that gap:

# Floating tag — trusts whatever v4 currently points to
- uses: actions/checkout@v4

# Pinned to an exact commit — the tag is a comment for humans only
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

Renovate has first-class support for this pattern via a preset — adding "helpers:pinGitHubActionDigests" to the extends array in renovate.json is enough to have Renovate automatically convert floating tags to pinned SHAs across every workflow file, and it keeps the trailing version comment updated as it bumps the digest going forward, so the file stays both secure and human-readable without anyone hand-maintaining the mapping between SHA and version.

Dependabot also supports the github-actions ecosystem and will bump pinned SHAs the same way it bumps npm versions:

- package-ecosystem: "github-actions"
  directory: "/"
  schedule:
    interval: "weekly"

Renovate vs Dependabot at a Glance

RenovateDependabot
HostingSelf-hosted app or Renovate-run GitHub AppNative to GitHub, zero setup
PlatformsGitHub, GitLab, Bitbucket, Azure DevOpsGitHub only
GroupingVery flexible, regex-based package rulesCoarser, dependency-type or update-type based
Digest pinning helpersBuilt-in presets for Docker + ActionsSupported, less turnkey
Config formatSingle renovate.json, shareable presetsdependabot.yml, per-ecosystem entries
Best forTeams wanting fine control, multi-platform orgsGitHub-only teams wanting zero infrastructure

A Reasonable Default Config

Putting the pieces together, a config that groups noise, automerges only what CI has already verified is safe, and keeps base images and Actions on pinned digests:

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:recommended",
    "helpers:pinGitHubActionDigests",
    "schedule:weekly"
  ],
  "timezone": "Europe/Paris",
  "packageRules": [
    {
      "matchUpdateTypes": ["patch", "pin", "digest"],
      "automerge": true,
      "automergeType": "pr"
    },
    {
      "matchUpdateTypes": ["minor", "major"],
      "automerge": false,
      "dependencyDashboardApproval": false
    }
  ],
  "lockFileMaintenance": {
    "enabled": true,
    "schedule": ["before 6am on the first day of the month"]
  },
  "vulnerabilityAlerts": {
    "automerge": false,
    "labels": ["security"]
  }
}

Note that even vulnerability fixes stay off automerge here — a security patch is exactly the kind of change worth a human glance, since the CVE it fixes is often accompanied by a behavior change that’s easy to miss in a fully automated pass.

Key Takeaways

  • Grouping related packages into one PR is the single change that turns dependency automation from noise into signal.
  • Schedule routine updates weekly; both tools bypass the schedule for security patches automatically.
  • Automerge should gate on CI status checks, never bypass them — it automates the merge click, not the verification.
  • Reserve automerge for patch/digest updates; minor and major bumps deserve a human reading the changelog.
  • Lockfile maintenance catches transitive drift that direct-dependency updates never touch.
  • Pin Docker base images and GitHub Actions by digest/SHA, and let Renovate or Dependabot keep the pin current — hand-pinning without automation just means it never gets updated.
  • Renovate offers finer-grained control and multi-platform support; Dependabot wins on zero-setup simplicity for GitHub-only repos.