The Keycloak Upgrade Ledger

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

2026-08-26 · run 2026-08-26-userstorage-artifact-split-narrowed

user-storage artifact split, narrowed: 24.0.0 (and a 25.0.3 Maven Central anomaly)

Host
local laptop; Maven container + curl
Condition
Narrow the model/storage split to a release (☐ row in both provider-types records)

Why this run existed

2026-08-26-provider-types established that org.keycloak.storage. UserStorageProvider moved out of keycloak-server-spi and changed Maven artifact — keycloak-model-legacy (≤ 23) → keycloak-model-storage (24+) — with keycloak-model-legacy gone by 25.0.6. It left the exact boundary open, bracketed to (23.0.7, 24.0.5]. This run closes the bracket by inspection of Maven Central coordinates and the published jars.

Environment

FieldValue
Artifacts inspectedkeycloak-model-legacy, keycloak-model-storage
Versions23.0.7, 24.0.0, 24.0.5, 25.0.0–25.0.6
MethodMaven Central directory listing + per-coordinate HTTP status + jar tf for org/keycloak/storage/UserStorageProvider.class
Hostlocal laptop; Maven container + curl

Findings

Finding 1 — the relocation happens at exactly 24.0.0 ⭐

UserStorageProvider.class moves between artifacts on the 23 → 24 boundary:

VersionUserStorageProvider.class in keycloak-model-legacyin keycloak-model-storage
23.0.7yesartifact not published
24.0.0noyes
24.0.5noyes

keycloak-model-storage is first published at 24.0.0, and from that release keycloak-model-legacy no longer contains the class. So the customer-relevant break is the 23 → 24 hop: a user-storage provider built against keycloak-model-legacy keeps its imports (org.keycloak.storage.*, unchanged) but must change its Maven coordinate to keycloak-model-storage at 24.0.0. Notably, keycloak-model-legacy is still published at 24.0.x — it just no longer carries UserStorageProvider, so a 24.x build that still declares the old coordinate resolves but fails to link the class.

Finding 2 — keycloak-model-legacy is dropped at 25.0.0, but 25.0.3 is a one-off anomaly ⭐

The publish history of keycloak-model-legacy on Maven Central is not a clean cut. Per-coordinate HTTP checks:

Versionkeycloak-model-storage POMkeycloak-model-legacy POM
25.0.2200404
25.0.3404200
25.0.4200404

keycloak-model-legacy is absent for 25.0.0–25.0.2, reappears at 25.0.3 and there carries UserStorageProvider.class again (verified by jar tf), then is gone again from 25.0.4 onward. The mirror image holds for keycloak-model-storage: published for every 25.0.x except 25.0.3, where it is missing.

So the two artifacts invert at exactly 25.0.3 — a one-off publishing anomaly in that release. Practical consequences, both worth a line in the assessment:

Finding 3 — the stable end state from 25.0.4

From 25.0.4 onward the state is what the earlier record reported: keycloak-model-storage published, keycloak-model-legacy gone. The split is real and permanent at 24.0.0; the 25.0.3 inversion is a transient anomaly, not a reversal of the move.

Verification

ClaimPrimary sourceChecked
keycloak-model-storage first published at 24.0.0Maven Central directory listing
UserStorageProvider.class in model-storage (not legacy) from 24.0.0jar tf of both artifacts at 23.0.7 / 24.0.0 / 24.0.5
model-legacy dropped for 25.0.0–25.0.2per-coordinate HTTP 404
model-legacy reappears at 25.0.3 carrying the classHTTP 200 + jar tf
model-storage missing at 25.0.3HTTP 404
stable end state from 25.0.4model-storage 200, model-legacy 404

Publishable extract

Your user-federation provider does not change its imports between Keycloak 23 and 24 — it changes its Maven coordinate.

org.keycloak.storage.UserStorageProvider moved from the keycloak-model-legacy artifact to keycloak-model-storage at exactly 24.0.0. The import line is identical; the dependency is not. The old artifact kept publishing through the 24.0.x line but stopped containing the class, so a stale build resolves and then dies at runtime — the worst kind of break.

And there is a one-release trap: at Keycloak 25.0.3 the two artifacts inverted on Maven Central — keycloak-model-storage was not published (404) and keycloak-model-legacy was (200, class present), before settling back at 25.0.4. A dependency audit that checks "does the coordinate resolve" rather than "which artifact actually carries the class" misses both halves.

← Back to the Ledger