There is no single `bundle update` task
A simple way to fix vulnerable gems, update dependencies in stages, and avoid turning bundle update into a gamble.
bundle update gets scary when a single command carries too much weight.
A CVE fix, a rubocop bump, a sidekiq minor release, and a rails upgrade do not belong in the same conversation. But they often land in the same lockfile diff anyway. I do not trust that kind of PR, and I do not expect anyone else to trust it either.
I do not think the problem is Bundler. The problem is treating dependency maintenance like one big chore instead of a few smaller jobs.
Here is the split I prefer.
Nothing clever. Just separate work with separate risk.
Pull security fixes out of the pile
If a gem is vulnerable, handle that first.
gem install bundler-audit
bundle audit --updateThen update only the gem you actually need to move:
bundle update --conservative --patch <gem-name>I like doing this in isolation because the goal is obvious. You are not “cleaning up dependencies.” You are removing a known problem.
That distinction matters in review and when something goes wrong. A security fix should not sit around waiting for someone to debug a broken formatter or a noisy minor update in a completely different part of the tree.
Move dev and test tooling on its own
After that, I usually take the lower-risk bundle next:
bundle update --conservative --group=development
bundle update --conservative --group=test
# Or:
bundle update --conservative --group test developmentIf your Gemfile groups things differently, adjust the commands to match. The point is to keep tooling updates away from runtime updates.
This is often the easiest place to make progress. If something breaks here, it usually breaks in CI, in local scripts, or in editor tooling. That is still annoying, but it is a very different kind of risk from changing gems that sit in the request path or talk to production services.
I also like that it gives you a smaller PR with a clear story: we refreshed the tools around the app, not the app itself.
Do runtime updates without the big gamble
This is where people reach for one big bundle update and hope for the best.
I would not.
Start with the cheapest pass:
bundle update --patch --strictThat usually clears a decent amount of drift without rewriting the whole dependency graph.
After that, slow down a bit. Run the test suite. Check the areas that matter. If the app has a few dependencies that tend to cause trouble, read their changelogs before you keep going.
Then use bundle outdated and decide what the next small batch should be. Maybe that is one background job stack. Maybe one API client. Maybe one gem that has been behind for a while and deserves its own PR.
bundle update --minor --strict <gem-name>
bundle update --major <gem-name>There is no prize for updating everything in one shot. I would rather review a few boring dependency pull requests than stare at one giant lockfile diff and guess.
Treat Gemfile constraints as real upgrade work
At some point, Bundler stops because Gemfile says no.
This is where I switch mental models:
bundle outdated --groupsIf a gem is blocked by a version pin or an upper bound, you are no longer doing routine maintenance. You are changing an explicit decision in the application.
That deserves more attention.
Sometimes the change is easy. Sometimes it needs code changes, rollout notes, or a dedicated ticket. Either way, I would not hide that work inside a general dependency refresh.
I care even more about this with gems close to the heart of the app: rails, database adapters, job processing, auth, anything that can quietly change behavior under load.
What this changes
The main benefit is not elegance. It is control.
Each diff has one reason to exist. That makes review less tiring, and when something breaks, you usually know where to look first.
That is the part people actually want from dependency maintenance. Not a perfectly current lockfile. Just a process that does not feel reckless.
Quick reference
Fix vulnerable gems first.
Update
testanddevelopmentgems separately.Use a patch pass for runtime dependencies before picking off smaller batches.
Treat
Gemfileconstraint changes and major upgrades as deliberate work, not lockfile churn.

