Use a Gradle dependency constraint to influence the version selected for a module without adding that module to your dependency graph. Constraints can govern direct or transitive modules, but their effect depends on the configuration and the kind of version requirement you declare.
What a dependency constraint does
Gradle describes a dependency constraint as a way to set version requirements for a module “without adding that module as a dependency.” The distinction matters when a transitive library brings in a module whose version you need to manage: you can guide resolution without declaring an extra direct dependency on that module.
A constraint participates in conflict resolution only if the module is otherwise present in the graph. For example, a constraint on Guava does not cause Guava to be downloaded when nothing depends on it.
Add a constraint to a configuration
In Kotlin DSL, declare the dependency where it is used and add a constraint in the relevant configuration context:
#1 Best Overall
dependencies {
implementation("com.google.guava:guava")
constraints {
implementation("com.google.guava:guava:33.0.0-jre") {
because("keep the dependency at a known compatible baseline")
}
}
}
Here, implementation declares Guava as a dependency without specifying its version. The matching constraint supplies a version requirement and applies in the implementation configuration context. Choose the configuration that corresponds to the dependency usage you intend to affect; a constraint declared in one context does not automatically mean every configuration has the same rule. See the Gradle dependency constraints guide.
Choose how strongly to control the version
A plain constraint is not a hard pin. It normally establishes a lower bound, so Gradle may select a higher version if other requirements in the graph call for it. Use a rich version when the rule needs to express more than that baseline.
Rank #2
| Requirement | Effect | When to use it |
|---|---|---|
| Normal version | Provides a requirement that generally allows selection of a higher version. | Set a compatible baseline while permitting upgrades during resolution. |
strictly("1.2.3") |
Restricts selection to the specified version or range; incompatible requirements can make resolution fail. | Enforce an exact version or a carefully bounded range. |
prefer("1.2.3") |
Signals a preferred version without requiring it if resolution needs another version. | Express a default choice that can yield to other requirements. |
reject("1.2.3") |
Excludes the specified version from consideration. | Prevent selection of a known unsuitable version. |
For example, a strict requirement can be written as implementation("group:module") { version { strictly("1.2.3") } } inside a dependency declaration, or as a rich version in a constraint. If requirements cannot be satisfied together, resolution fails rather than silently choosing a version outside the allowed requirements. The Gradle version declarations guide explains version requirements and rich versions.
Use constraints to manage transitive dependencies
Constraints are transitive when published as dependency metadata. Suppose library A depends on library B, and B declares a constraint that module C must be at least version 3. If a consumer also requests C at version 2, Gradle can resolve C at version 3. The constraint communicates a compatibility requirement for a module that B does not itself add as a direct dependency.
Recommended Free Tools
This is useful when a library needs consumers to avoid an older or incompatible version of another module, while keeping that module optional unless the dependency graph otherwise includes it.
Share rules across a multi-project build with a platform
For a build with several projects, Gradle recommends centralizing shared constraints in a platform built with the java-platform plugin. A minimal Kotlin DSL example is:
plugins {
`java-platform`
}
dependencies {
constraints {
api("com.google.guava:guava:33.0.0-jre")
api("org.slf4j:slf4j-api:2.0.9")
}
}
Projects can consume the platform so they share its constraints instead of maintaining duplicate version rules. Gradle documents platforms and version catalogs as centralization options in its dependency management guide.
Constraints, version catalogs, and dependency locking
These tools solve related but distinct problems. A catalog makes coordinates and requested versions reusable and discoverable; a constraint participates in resolution; dependency locking records resolved versions for repeatable builds.
| Approach | Adds a module to the graph? | Can affect transitive modules? | Allows a higher version? | Shareable across projects? | Published rule preserved? |
|---|---|---|---|---|---|
| Dependency constraint | No; it only acts when the module is otherwise present. | Yes, when the constraint reaches the consumer through applicable metadata. | Usually yes for a normal constraint; rich versions can prefer, reject, or restrict versions. | Yes, directly or through a platform. | Gradle Module Metadata preserves constraints for Gradle consumers; Maven or Ivy consumers may not. |
| Version catalog | No; an alias supplies a coordinate or requested version for a declaration. | Not by itself as an enforced resolution rule. | Yes; another request or constraint may lead Gradle to select a different version. | Yes; catalogs centralize aliases and requested versions. | Not an enforcement mechanism for published transitive constraints. |
| Dependency locking | No; it does not add a dependency. | It records resolved versions for dependencies in the relevant configuration. | It keeps resolution aligned with recorded versions until locks are updated. | Lock state can be maintained by a project or build setup. | It is distinct from publishing constraints as module metadata. |
Use a catalog when the main goal is a single, readable place for dependency aliases and requested versions. Choose a constraint or platform when you need to shape version selection. Use locking when the goal is to preserve the versions a build has already resolved. Gradle explains catalog behavior in its version catalogs guide and locking in its dependency locking guide.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Inspect resolution and account for publication metadata
Gradle normally considers requested versions across the dependency graph and selects the highest version that satisfies the requirements. Constraints participate in that process: they can raise the minimum, narrow the allowed range, reject versions, or make a selection strict. If no version satisfies all requirements, Gradle reports a resolution failure with an explanation.
When a selected version surprises you, inspect the resolved dependency graph and the configuration involved, then check which dependencies and constraints requested the module. Pay particular attention to whether a constraint is normal or strict and whether another requirement conflicts with it; the constraint guide covers constraint behavior.
Published constraints are carried by Gradle Module Metadata. They are fully supported when both publisher and consumer use Gradle, but Maven or Ivy consumers may not preserve them. If downstream consumers use those tools, do not rely on a published Gradle constraint alone as an enforcement mechanism.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

