In a large team, a lot gets built. The question is: will everything that gets built also get proper maintenance? Keeping dependencies up-to-date is one of the highest ROI activities you can automate. This post shows how I use Renovate to keep projects healthy without turning dependency updates into a full‑time job.
Renovate is a bot that scans your repositories, detects outdated dependencies, and creates pull requests with version bumps and changelogs. It supports many ecosystems (npm, NuGet, Docker, GitHub Actions, Terraform, Bicep, etc.) and can be run as a GitHub App, a self-hosted Docker container, or inside CI (e.g., Azure DevOps, GitHub Actions).
Key things I like:
Automated PRs with helpful titles and release notes (when GitHub tokens are configured)
Smart grouping (e.g., group non‑breaking updates, keep majors separate)
Auto-merge for safe updates once checks pass
Custom schedules so updates arrive when your team can handle them
Wide ecosystem support across backend, frontend, infra, and pipelines
Create a renovate.json in the repository root. Here is a battle-tested baseline that mirrors how I like to structure PRs for frontend, backend, and infra:
For Azure DevOps, I like to run Renovate via a scheduled pipeline. This uses the built-in System.AccessToken so you don’t have to manage a personal token. Ensure “Allow scripts to access the OAuth token” is enabled on the pipeline.
For private registries, provide credentials via config files and environment variables.
Note: In Azure DevOps pipelines, authentication to private feeds can be injected automatically (no tokens/passwords needed in .npmrc/NuGet.Config). Ensure the pipeline has access to the feeds and OAuth token access is enabled (or use dedicated authenticate tasks). You must still include the private feed references (registries/scopes/URLs) in these files so tools know where to resolve packages.
npm: add a root-level .npmrc and ensure the token env var is available in the pipeline step (the example above passes a token via environment variables).
NuGet: add a root-level NuGet.Config for restores, and/or configure Renovate hostRules (as shown below) so Renovate can fetch metadata from private feeds.
When running Renovate in CI or Docker (i.e., not via the GitHub App), provide a root‑level config.js or pass --config-file to point to it. Minimal example for the Azure DevOps setup above:
Provide a work-item to link if applicable (some teams have a 'maintenance' item, or create a new item every sprint)
Per project; 4 package rules + extra's
Backend dependencies non-breaking
Backend dependencies breaking
Frontend dependencies non-breaking
Frontend dependencies breaking
Extra's: Bicep/Terraform/Github Actions
Extra's: My.Company.\* dependencies
How this maps to renovate.json:
Non‑breaking updates are grouped per ecosystem: "npm packages for non‑breaking versions" and "nuget packages for non‑breaking versions", and will auto‑merge once checks pass. NPM uses rangeStrategy: "bump".
Breaking updates are isolated into "Breaking updates npm" and "Breaking updates nuget". Majors go here by default; pinned NPM deps and ~‑ranged minors are treated as breaking; NuGet pre‑1.0 updates are treated as breaking.
Internal NuGet packages matching My.Company get a dedicated group: "My.Company package updates nuget".
Global auto‑merge is enabled (automerge: true) with merge commits (automergeType: "pr", automergeStrategy: "merge-commit").
Operational: runs on Azure DevOps (platform: "azure"), no PR rate limit (prHourlyLimit: 0), and common folders are ignored (node modules, bower components).
In total that should make 4-6 PRs at a time for the configured repository.
Final tips:
Start conservative, then turn on auto‑merge for low-risk groups once you trust the flow.
Keep CI fast and reliable—Renovate is only as smooth as your test signal.
Use schedules to avoid a Monday PR flood or weekend noise.