Use Gradle's module replacement rule. It substitutes one module for another across the whole build, including transitive requests, with a written reason. It suits a drop-in fork or successor that keeps the same API. It is a blunt tool, so test hard and record why it exists.
What the documentation offers
Gradle's resolution rules page lists several strategies: forcing a version, module replacement, dependency substitution, and others. It describes module replacement as substituting one module for another with an explanation. The page also gives a warning worth reading: these mechanisms inject rules directly into the resolution engine, so they can be considered brute-force solutions that may mask underlying issues, such as the introduction of new dependencies. It advises using them only when other approaches are insufficient, and says that if you are building a library, dependency constraints are better since they are shared with consumers.
One limit is stated outright: Gradle does not currently support replacing a module with multiple modules, but multiple modules can be replaced by a single module.
When replacement is the right move
| Situation | Replacement fits? |
|---|---|
| A maintained fork keeps the same API and coordinates changed | Yes |
| A successor project offers a compatible drop-in | Yes, after testing |
| The successor has a different API | No, migrate the code instead |
| One module split into several | No, not supported as one to many |
| A version bump would be enough | No, use a constraint |
Replacement works at the module level, so it does nothing about code that imports classes under the old package name. If the fork renamed its packages, direct usages in your source must change, and a replacement rule will not help.
Steps
- Confirm the old library is the problem: abandoned, unpatched, or flagged without a fix.
- Choose the replacement and read its security history. A fork is only better if someone maintains it.
- Check API and binary compatibility for the classes you and your dependencies actually use.
- Add the rule with a clear explanation string that names the advisory and date.
- Resolve the dependency tree and confirm the old module no longer appears.
- Run the full test suite, including integration tests that exercise the libraries that pulled in the old one.
- Put an owner and a review date on the rule.
Risks to name in the pull request
The replaced module's transitive dependents were written against the old one. Subtle behavior differences, serialization formats, and default settings can differ even when signatures match. Also check the replacement's own dependencies: you may be trading one set of advisories for another.
Finally, a rule like this is easy to forget. If the original project revives, or the replacement is abandoned, nobody will notice unless the rule has an owner. See the related guide on when to fork an abandoned dependency.
Try it yourself
Click through it at your own pace, or open it full screen. Check how many parents pull in the same library, because each one is a consumer of your replacement.
Where Safeguard fits
Safeguard scans dependencies, runs reachability analysis to show which findings your code can actually reach, and can open fix pull requests through autonomous remediation. That last feature is off by default and every category starts on Manual, so a person approves each change. You can try a free scan on a repository first.
Quick check
Can Gradle replace one module with several?
No. The documentation says multiple modules can be replaced by a single module, but not the reverse.
Should a library publish module replacement rules to its users?
No. The Gradle docs say library authors should prefer dependency constraints, which are shared with consumers.
Sources
Last reviewed: 19 October 2026.