From days of manual patching to a pull request

For teams on GitHub Enterprise Server (GHES), Dependabot is now generally available for securing and updating dependencies. As someone who spent five years working on GHES-hosted code before joining GitHub, I know exactly what this means for developers who have been managing dependency updates by hand.

Consider a typical Rails project: rails new produces an app with 74 dependencies, Django apps start with 88, and a Create React App project has 1,432. When a security advisory is published, addressing it means tracking down release notes, patching each affected app, opening a pull request, waiting for CI, getting reviews, and deploying—a process that could take days.

In my previous role, my team maintained 14 Rails apps in a microservices architecture, each with dozens of dependencies across Ruby, Elixir, Python, JavaScript, and PHP. Patching a single vulnerability across all of them meant repeating the same tedious workflow for every app. Every hour spent on that was an hour not spent on features customers could see. Teams inevitably end up weighing which vulnerabilities are likely to be exploited and which can wait.

With Dependabot security updates, that workflow starts with a pull request. What took an engineer days could be done before lunch.

The cost of deferring upgrades

Keeping dependencies current has its own challenges. One of my previous teams was still running Rails 3.2 when Rails 6 shipped six years later. By then, support had long since phased out, and we were applying our own security patches instead of receiving them from the framework. Upgrading became even harder, and we spent years deferring the work as other priorities took precedence.

Incremental upgrades are easier and lower-risk, and they give attackers less time to exploit known flaws. Dependabot version updates would have opened pull requests for each new Rails release. We would still have had to verify changes to our code, but the work would have been spread out across releases instead of becoming a P0 emergency.

When I joined GitHub in 2021 to work on Dependabot, the team was just starting to bring it to GHES. It quickly became clear why that hadn't happened sooner. After GitHub acquired Dependabot in 2019, the team scaled it to secure millions of repositories by porting the backend to run on Github's Kubernetes-based platform, Moda. Dependency update jobs were moved to lightweight Firecracker VMs, allowing Dependabot to generate millions of pull requests in hours.

That architecture doesn't translate to GHES, where everything runs on a single server with limited resources. For GHES, the team ported Dependabot's backend to Nomad, the container orchestration option on GHES. The work previously running on Firecracker VMs now runs on customers' hardware. Because organizations can self-host GitHub Actions runners in GHES, Dependabot jobs were adapted to run on GitHub Actions. Development processes also shifted to support continuous delivery in the cloud alongside the less frequent GHES release cadence.

For my former teammates, the workflow is now:

  • View the already-open pull request
  • Review the pull request and the release notes that are included
  • Deploy, observe, and merge

That's the outcome we set out to achieve: developers on GHES get the same dependency automation as cloud users, without weeks of manual upgrades or mounting technical debt.