The Keycloak Upgrade Ledger

Every upgrade we have rehearsed, with the environment stated and the clock running.

2026-08-26 · run api-removals-by-hop

Keycloak public-API removals, by upgrade hop

Condition
Standing report, not a rehearsal of a version pair: the measured public-API removal surface per upgrade hop, cited by four records and the custom-SPI post

Results

"Added" is included so the removal count is read against a surface that is growing, not shrinking.

Patch hops

HopRemovedAdded
26.7.0 → 26.7.109
26.7.1 → 26.7.203
26.7.2 → 26.7.3412

Minor hops, inside major 26

HopRemovedAdded
26.0.0 → 26.1.046228
26.1.0 → 26.2.017260
26.2.0 → 26.3.0137212
26.6.0 → 26.7.078374

Major boundaries

HopRemovedAdded
21.1.2 → 22.0.5277286
22.0.5 → 23.0.761314
23.0.7 → 24.0.5175522
24.0.5 → 25.0.6128680
25.0.6 → 26.0.068300

Spans

SpanRemovedAdded
26.0.0 → 26.7.1 (within one major)4002,310
21.1.2 → 26.7.1 (five majors, direct)9074,210

Findings

1. Patch releases are nearly clean — until a security rework reaches in

26.7.0 → 26.7.1 and 26.7.1 → 26.7.2 removed nothing. Every minor hop measured removed between 17 and 137 signatures. The first patch hop to remove anything is 26.7.2 → 26.7.3, which removed 4 — and all four are security- rework casualties, not routine cleanup:

So "patch = safe" still holds for routine patch releases, but a patch that bundles a security batch can carry removals. Treat the advisory batch as the unit of breakage risk, not the version-number increment.

2. The major/minor boundary does not predict breakage

26.2.0 → 26.3.0 removed 137 — in the same band as the 23.0.7 → 24.0.5 major boundary (175) and roughly twice 25.0.6 → 26.0.0 (68). Staying inside a major is not protection. Only the patch level is.

3. Staying inside one major is not a small distance

26.0.0 → 26.7.1 removed 400 signatures — more than any single major boundary measured, and 44% of the total across five majors (907).

4. This sharpens the corrected ledger thesis

Entry 01 now says the support window is one major wide and coverage of minor lines varies per batch. Combine that with the numbers above:

When an advisory batch tells you the fix is in 26.4.14 and you are on 26.0.x, that is not a patch. It is four minor hops, and on this evidence those hops remove on the order of 200 public API signatures. If you run custom extensions, the "just patch" path and the "upgrade project" path can be the same path.

That is a claim no vendor makes and no release note states, and it is measured rather than argued.

5. The model-artifact relocation is where the widened diff bites

The 2026-08-25 pass said 23.0.7 → 24.0.5 removed 145 and 24.0.5 → 25.0.6 removed 94. With the model artifacts included those are 175 and 128 — an extra 64 signatures across two hops, all of it in the artifacts a custom user-storage provider compiles against:

The reverse direction is not a removal but a relocation: a user-storage provider built against ≤23 references classes whose FQN still exists in 25+, but now ships in keycloak-model-storage. That survives a source-compatible rebuild (build-spi.sh needs the new artifact in the pom — see the operational notes), but a jar compiled against the old coordinates is the "which artifact, not which API" trap.

For the brittle (removed-API) side of that question — whether such a provider fails at load vs at first use — see the provider-types record; that is a runtime test, not a signature diff.

Caveats

← Back to the Ledger