CONCEPT Cited by 1 source
Transitive-dependency override build¶
Definition¶
A transitive-dependency override build is a build-system
configuration that forces a specific version of a library
pulled in transitively (via another dependency), overriding
the transitive resolver's default choice. In Maven this is a
<dependencyManagement> entry or an explicit direct
<dependency> pinning; in Gradle it's a resolution strategy
force or module substitution.
The technique matters on this wiki specifically when the override lets a downstream consumer adopt a patched version of an indirect dependency without upgrading the intervening direct dependency that normally controls it.
The load-bearing use case¶
Zalando's 2023-11-08 post (sources/2023-11-08-zalando-patching-the-postgresql-jdbc-driver) canonicalises this at the JVM / Postgres / Debezium altitude:
- Zalando's Postgres-sourced event-streaming applications depend on Debezium directly.
- Debezium pulls in pgjdbc transitively.
- For backwards-compatibility reasons, Zalando's apps pin an older Debezium major; that Debezium doesn't pull in pgjdbc 42.7.0+ with Zalando's upstream KeepAlive-LSN- advancement fix.
- Option 1: upgrade Debezium (breaks backwards compatibility).
- Option 2: override the transitive pgjdbc to a locally-
built
42.6.1-patchedvariant that backports the fix.
Zalando chose option 2. Verbatim:
"our applications do not use the latest version of Debezium and, by extension, do not use the latest version of PgJDBC which is pulled in as a transitive dependency by Debezium. In order to take advantage of the fix while still maintaining this backwards compatibility, we modified our build scripts to optionally override the latest version of the transitive PgJDBC dependency."
Structural property¶
The technique has two load-bearing properties:
- Decouples two upgrade cadences. The direct dependency's version stays pinned; the transitive dependency's version moves. Useful when the direct dependency's upgrade has orthogonal costs (breaking changes, API renames, behaviour drift).
- Requires build-script support, not source-code changes. Zero application code changes are required to ingest the fix — it lands at the build / classpath layer.
Operational mechanics (Maven example)¶
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.1-patched</version> <!-- locally built -->
</dependency>
</dependencies>
</dependencyManagement>
Zalando's post discloses that the override was conditional — the build scripts can produce both the unchanged image and the patched image from the same source tree. This is load- bearing for their rollout pattern (patterns/parallel-docker-image-prod-vs-test-for-patched-library): the two-image fan-out is a build-option toggle, not a branch in source control.
Hazards¶
- Classpath conflict with the direct dep's declared range.
If Debezium expects pgjdbc
>=42.5 <42.7, forcing 42.6.1- patched or 42.7.0 may violate Debezium's compatibility assumptions. - Signed-artifact invalidation. A locally-built patched jar is not signed by the upstream maintainer; security policies that verify Maven Central signatures will flag it.
- Fleet-wide rebuild cost. In an architecture with N independent per-stream JVM applications (e.g. systems/zalando-postgres-event-streams), a transitive- override rollout means N Docker image rebuilds — structurally distinct from a shared Connect-cluster upgrade where one cluster-wide bounce takes effect everywhere.
Relationship to adjacent patterns¶
- patterns/parallel-docker-image-prod-vs-test-for-patched-library — the rollout shape that wraps the override: build two images (unchanged + patched), verify patched in test, roll to production.
- patterns/client-driver-fix-over-application-workaround — the architectural lever that motivates overriding at the driver layer.
- patterns/upstream-the-fix — the strategic choice that produces the patched library; override is the tactical means to deliver it pending maintainer-driven transitive uptake.
- patterns/dependency-update-discipline — the broader hygiene practice around keeping dependency graphs current.
Seen in¶
- sources/2023-11-08-zalando-patching-the-postgresql-jdbc-driver
— canonical wiki introduction. Zalando's disclosure: "we
modified our build scripts to optionally override the latest
version of the transitive PgJDBC dependency", producing a
locally-built
42.6.1-patchedjar and two Docker images (patched + unpatched) that went to test and production respectively.