SPI Packaging and Deployment Strategy in Keycloak
Writing a custom Keycloak extension is the easy part. Getting it reliably built, versioned, deployed, and upgraded across a real fleet of servers without breaking logins — that's the actual engineering problem.
Imagine a pharmaceutical company that’s perfected a new medicine in the lab — but has no reliable process for manufacturing it consistently, packaging it safely, shipping it to pharmacies, and eventually recalling a batch if something goes wrong. The lab work, however brilliant, is only half the job. Building a custom Keycloak extension — an event listener, a custom required action, a credential provider — is exactly like that lab work: the interesting, creative part. SPI Packaging and Deployment Strategy is everything that comes after: how that custom code gets built into a reliable artifact, how it’s placed correctly into a running Keycloak instance, how it behaves across upgrades, and how a team safely rolls it back if something breaks. This guide, written for an audience comfortable with software engineering practice but perhaps new to Keycloak’s specific extension mechanics, covers what SPI packaging actually involves, the architecture of how Keycloak discovers and loads extensions, what happens internally at startup and deployment time, and how real engineering teams build a dependable, repeatable strategy around this. No prior background in Keycloak’s plugin system is assumed.
1Core Concepts
What is an SPI, again, and why does packaging matter for it?
An SPI — Service Provider Interface — is one of Keycloak’s many deliberately open extension points: event listeners, required actions, authenticators, user storage providers, and others. Writing code against one of these interfaces produces custom logic, but that logic is useless to a running Keycloak instance until it’s correctly packaged — bundled into a specific artifact format — and deployed — placed where Keycloak actually looks for and loads such artifacts at startup. The gap between “I wrote working code” and “Keycloak is actually running my code in production” is exactly what packaging and deployment strategy addresses.
Why isn’t this just “copy the file and restart”?
For a single developer testing one small extension on a laptop, copying a file and restarting genuinely might be the whole story. But a real production deployment introduces every concern that distinguishes a quick script from dependable infrastructure: multiple servers that all need the same artifact consistently, a need to track exactly which version of custom code is running where, a requirement to test new versions safely before they reach real users, and a need to roll back quickly if a new version causes a problem — all while Keycloak itself continues serving live logins.
Think of the difference between a home cook trying a new recipe once for dinner, and a restaurant chain rolling that same recipe out across five hundred locations. The recipe itself — the actual creative content — might be identical. But the restaurant chain needs consistent ingredient sourcing, quality control, a rollout plan, and a way to pull the dish from menus everywhere if a problem is discovered. SPI packaging and deployment strategy is exactly that industrial-scale discipline, applied to custom Keycloak code instead of a recipe.
Why does Keycloak keep custom code separate from its own core?
Keycloak’s own code ships as part of its core distribution, built, tested, and released by its maintainers on their own schedule. Custom organizational code is deliberately kept separate — packaged independently and deployed alongside, rather than merged into Keycloak’s own source — so that an organization’s extensions can be developed, versioned, and upgraded on their own timeline, without needing to fork or modify Keycloak itself. This separation is precisely what makes Keycloak’s SPI model sustainable at all: without it, every organization with a custom need would need to maintain its own fork of the entire product.
Any organization running one or more custom event listeners, required actions, authenticators, or user storage federation providers in production needs a deliberate packaging and deployment strategy the moment that custom code needs to reliably reach more than a single test instance.
Key vocabulary, explained simply
JAR (Java Archive)
The standard packaged format custom Keycloak extension code is typically compiled and bundled into, the actual artifact that gets deployed.
Providers Directory
The specific location within a Keycloak installation where deployed extension JARs are placed for Keycloak to discover at startup.
Provider Registration Descriptor
A metadata file bundled inside the JAR that tells Keycloak which SPI interfaces the packaged code actually implements.
Build Pipeline
The automated process — typically involving a build tool, testing, and artifact packaging — that turns source code into a deployable JAR consistently and repeatably.
Server Build/Augmentation Step
A step in modern Keycloak’s startup process where the server incorporates newly deployed providers into its runtime configuration, sometimes requiring an explicit rebuild trigger.
Rollback
The process of removing or reverting a deployed extension version, returning the server to its previous, known-good behavior.
2Standards, Formats & the Loading Mechanism
The standard Java service-provider discovery mechanism
Keycloak’s SPI loading builds on Java’s own long-standing standard mechanism for service discovery: a packaged JAR includes a specific metadata file, conventionally located within the archive, listing the fully qualified class names of the provider factories it implements for a given SPI. When Keycloak scans its providers directory at startup, it uses this same standard discovery mechanism to find and register every implementation it can locate, without needing any custom, Keycloak-specific registration step beyond correctly following this convention.
Why building on a Java standard, rather than a Keycloak-specific format, matters
Relying on Java’s existing, well-established service-loading convention means the packaging format for a Keycloak extension is, at its core, identical to how countless other Java libraries and plugins register their own extensions. A developer already familiar with this broader Java ecosystem pattern isn’t starting from zero when packaging a Keycloak provider — the specific SPI interfaces are Keycloak’s own, but the packaging mechanics around them are not a bespoke invention.
Think of a shipping container’s standardized dimensions, used across every port, ship, and crane in the world, regardless of what’s actually inside a given container. A port doesn’t need special handling equipment for containers from any particular shipping company — because every container follows the same external standard. Java’s service-provider discovery mechanism plays the same role for packaged code: Keycloak’s loading machinery doesn’t need special-case logic for any particular organization’s extension, because every properly packaged JAR follows the same underlying convention.
Modern Keycloak’s build-time augmentation step
Contemporary Keycloak, built on the Quarkus framework, introduces an additional consideration beyond simply dropping a JAR into a directory: certain configuration and optimization work happens during a distinct build phase, sometimes requiring an explicit rebuild step after new providers are deployed, so the server’s runtime configuration correctly reflects the newly available extensions before it actually starts serving traffic. Understanding whether a given deployment approach requires this explicit step — and building it into the deployment pipeline — is a specific, version-relevant detail worth confirming against current official documentation rather than assuming based on older or different deployment models.
Simply copying a new provider JAR into the providers directory and restarting the process is not always sufficient by itself on every Keycloak distribution and version — depending on the specific build and deployment approach in use, an explicit rebuild step may be required for the new provider to actually be recognized and correctly wired into the running server.
Why this matters for a packaging and deployment strategy specifically
Getting these mechanics precisely right is exactly what separates a reliable, repeatable deployment pipeline from one prone to mysterious, hard-to-diagnose failures — a JAR that’s correctly built but improperly registered, or a rebuild step silently skipped, produces the exact same symptom (the extension simply doesn’t seem to work) as a genuine bug in the extension’s own logic, making a clear understanding of the loading mechanism itself essential for efficient troubleshooting.
META-INF/services convention
The standard Java location within a JAR where provider factory class names are registered, following the broader Java service-loading pattern.
Providers directory scan
Keycloak’s startup-time process of examining its designated providers location for deployable artifacts.
Build/augmentation phase
A distinct step in modern Keycloak’s startup sequence that incorporates newly available providers into the server’s optimized runtime configuration.
Classpath isolation
The consideration of how a custom provider’s own dependencies interact with, or potentially conflict with, Keycloak’s own internal dependencies once loaded together.
3Architecture & Components
graph TB
SRC[Source Code Repository] --> BUILD[Build Pipeline]
BUILD --> TEST[Automated Tests]
TEST --> ART[Packaged JAR Artifact]
ART --> REPO[Artifact Repository/Registry]
REPO --> STAGE[Staging Keycloak Instance]
STAGE --> VERIFY{Verified Working?}
VERIFY -->|yes| PROD[Production Keycloak Fleet]
VERIFY -->|no| FIX[Back to Development]
PROD --> MON[Monitoring & Rollback Readiness]
Component breakdown
Source Control and Build Pipeline
Where custom extension code lives and is compiled, tested, and packaged into a versioned JAR artifact, ideally through an automated, repeatable process rather than a manual, ad hoc build.
Artifact Repository
A versioned storage location for built JAR artifacts, allowing a specific, known version to be reliably retrieved and deployed, rather than relying on whatever happens to be on a developer’s machine.
Deployment Automation
The tooling responsible for actually placing a specific artifact version into a Keycloak instance’s providers directory, and triggering any necessary rebuild step, across every server in a cluster.
Staging and Verification Environment
A non-production Keycloak instance, configured as closely as possible to production, where a newly built artifact is deployed and verified before ever reaching real users.
Where this fits into a broader Keycloak operational strategy
SPI packaging and deployment strategy doesn’t exist in isolation — it needs to be coordinated with an organization’s broader Keycloak upgrade strategy (rolling upgrades, in particular), since a custom extension’s own compatibility with a new Keycloak version is exactly the kind of thing that needs verification alongside any core Keycloak version upgrade, not as an afterthought discovered only after the core upgrade has already begun.
A common real setup
A company maintains its custom event listener and required action extensions in a dedicated source repository, with a continuous integration pipeline that builds, tests, and publishes a versioned JAR to an internal artifact repository on every change. A deployment automation tool then handles pulling a specific, approved version and rolling it out across the Keycloak cluster’s providers directories, coordinated with the cluster’s own rolling upgrade tooling to avoid any node running an unexpectedly mismatched combination of Keycloak core version and extension version.
Why treat this with the same rigor as any other production deployment pipeline?
Because custom SPI code runs with the same trust and process-level access as Keycloak’s own core code, a poorly managed deployment — an untested artifact, an inconsistent version across cluster nodes, a missing rebuild step — carries real risk to the availability and correctness of the entire login system. Treating this pipeline with the same engineering discipline given to any other critical production deployment is not optional caution; it’s a direct reflection of how much the rest of the organization depends on Keycloak functioning correctly.
4Internal Working
What happens at a fresh startup
When a Keycloak instance starts, it scans its configured providers directory, locates every correctly packaged JAR present, reads each one’s service-registration metadata to determine which SPI interfaces it implements, and constructs the necessary provider factories accordingly. On a modern, Quarkus-based Keycloak distribution, this discovery may be incorporated as part of an explicit build/augmentation step that optimizes the server’s startup for the specific set of providers present, meaning the providers available at the time that build step runs are exactly what the resulting running server will have access to.
What’s different about updating an already-running cluster
Adding, updating, or removing a provider on a node that’s already running typically requires that node to be restarted (and, depending on the distribution’s build model, potentially rebuilt) for the change to take effect — providers are generally not hot-swappable into a live, running process without some form of restart. This is precisely why deploying a new or updated extension version to a production cluster follows the same node-by-node, drain-restart-verify-rejoin discipline used for a broader Keycloak version upgrade, rather than being treated as a lighter-weight, live configuration change.
Version consistency across a cluster
Because a cluster typically shares a common database and session store, it matters that every node in the cluster is running a consistent, compatible version of any given custom extension during normal operation — a cluster where some nodes run an older extension version and others run a newer, behaviorally different one can introduce inconsistent behavior for users depending on which node happens to serve their request, which is a genuinely different and additional concern beyond the Keycloak-core-version compatibility already discussed for rolling upgrades generally.
Even when a rolling upgrade of Keycloak’s core version itself is well understood and tested, simultaneously rolling out a new version of a custom extension across the same cluster introduces its own, separate mixed-version consideration — the custom code’s own backward and forward compatibility during the transition period deserves the same deliberate scrutiny as Keycloak core’s own.
Step-by-step: deploying a new extension version to a production cluster
New version built and tested
The updated extension code is compiled, automatically tested, and packaged into a new, versioned JAR artifact.
Staging deployment and verification
The new artifact is deployed to a staging environment and verified to behave correctly before any production rollout begins.
First production node updated
Following the same drain-and-restart discipline used for core version upgrades, one node’s providers directory is updated with the new artifact.
Node rebuilt and restarted
Any necessary build/augmentation step is triggered, and the node restarts with the new provider version active.
Health verified before proceeding
The updated node’s behavior is confirmed correct before it rejoins live traffic and before the next node’s update begins.
Remaining nodes updated in sequence
The process repeats across the rest of the cluster until every node runs the new, consistent extension version.
5Data Flow & Lifecycle
sequenceDiagram
participant Dev as Developer
participant CI as Build Pipeline
participant Repo as Artifact Repository
participant Staging
participant Prod as Production Cluster
Dev->>CI: Commits extension code change
CI->>CI: Builds and runs automated tests
CI->>Repo: Publishes versioned JAR artifact
Repo->>Staging: Deploys specific version for verification
Staging->>Staging: Manual/automated verification
alt Verified successfully
Repo->>Prod: Rolled out node by node
Prod->>Prod: Health-checked at each step
else Verification fails
Staging-->>Dev: Issue reported, fix required
end
Notice that production deployment only happens after successful staging verification in this diagram — this gate is what turns “we have a new version of the code” into “we have confidence this new version is safe to run against real user logins.” Skipping or rushing this gate is precisely where many production incidents involving custom extensions originate, since a bug caught in staging costs nothing but development time, while the same bug reaching production can genuinely disrupt real user logins.
The lifecycle of a deployed extension version
Developed and versioned
Code changes are committed, built, and assigned a clear, trackable version identifier.
Verified in staging
The specific version is deployed to a representative non-production environment and confirmed to behave correctly.
Rolled out to production
The version is deployed across the production cluster, following a controlled, node-by-node sequence.
Monitored in active use
The deployed version’s behavior is observed in production, with rollback readiness maintained in case an issue emerges.
Superseded or retired
Eventually, a newer version replaces it through the same pipeline, or the extension itself is retired entirely if no longer needed.
Maintaining the previous, known-good artifact readily available in the artifact repository — not just the newest version — is what actually makes a rollback fast and low-risk when needed; a rollback plan that depends on rebuilding an old version from source under time pressure during an active incident is considerably riskier than one that simply redeploys an already-built, already-verified prior artifact.
6Advantages, Disadvantages & Trade-offs
Advantages
- Makes deploying and updating custom extensions predictable and repeatable, rather than a manual, error-prone, one-off process
- Provides clear versioning, making it straightforward to know exactly what code is running on any given server at any time
- Enables fast, low-risk rollback when a problem is discovered, rather than a scramble to reconstruct a previous working state
- Integrates naturally with a broader rolling upgrade discipline, treating extension updates with the same operational rigor as core version upgrades
Disadvantages & Trade-offs
- Requires real upfront investment in build automation, artifact management, and staging infrastructure
- Adds process overhead compared to a quick, manual “just copy the file” approach, especially noticeable for very small, low-stakes extensions
- Demands ongoing coordination between extension deployment and core Keycloak version upgrades, adding planning complexity
- Classpath and dependency conflicts between custom code and Keycloak’s own internals can be subtle and occasionally difficult to diagnose
Setting up a proper manufacturing and quality-control pipeline for a product takes real investment before the first item ever ships — but it’s exactly what prevents a defective batch from silently reaching customers, and exactly what allows a clean, fast recall if something does go wrong later. The upfront cost of that pipeline is real, but the alternative — discovering a problem only after it’s already affected real users, with no clear way to trace or reverse it — is considerably more expensive.
7Security
Verifying artifact integrity throughout the pipeline
An artifact that’s built, tested, and verified in staging is only as trustworthy as the guarantee that the exact same artifact — not a tampered or substituted one — is what actually reaches production. Using checksums or signatures to verify artifact integrity at each handoff point in the pipeline, and restricting who can publish to or deploy from the artifact repository, closes off a meaningful supply-chain risk that’s easy to overlook when focus is placed entirely on the extension’s own code correctness.
Context
Teams often focus security review entirely on a custom extension’s own source code, while giving comparatively little scrutiny to the build and deployment pipeline that turns that source code into a running production artifact.
Decision
Apply the same access-control, integrity-verification, and audit-logging rigor to the build pipeline and artifact repository as is applied to production Keycloak access itself, treating the deployment pipeline as part of the identity system’s own security perimeter.
Consequence
A compromised build system or artifact repository cannot become a silent path for malicious code to reach production with the same trust level as Keycloak’s own core, closing a supply-chain gap that pure code review alone would miss.
Dependency management and third-party libraries
Custom extensions frequently pull in third-party libraries as dependencies, and each of those libraries becomes, in effect, part of the code running with Keycloak’s own trust level once deployed. Applying the same dependency-vulnerability scanning and update discipline used for any other production software to a custom extension’s dependency tree is essential — a vulnerability in a seemingly unrelated third-party library, pulled in transitively, can become a genuine security exposure inside the identity system itself.
Treating a custom extension’s third-party dependencies as a one-time concern addressed only when the extension was first written, rather than an ongoing responsibility requiring periodic review and updates as new vulnerabilities are discovered in those dependencies over time.
Least-privilege access to the deployment pipeline itself
Given that anyone able to publish an artifact to the repository or trigger a production deployment effectively has the ability to run arbitrary code inside Keycloak’s own process, access to these specific pipeline capabilities deserves the same careful, least-privilege scoping given to any other highly privileged administrative capability — not broad, convenient access for an entire engineering team by default.
8Monitoring, Logging & Metrics
Deployment success/failure rate
Tracking how often deployments of new extension versions complete successfully versus require intervention, useful for spotting a degrading pipeline before it causes a larger production incident.
Version consistency across cluster nodes
Periodically verifying every node in a cluster is running the expected, intended extension version, catching any node that was accidentally missed during a rollout.
Time from build to production
Measuring how long a verified artifact typically takes to reach production, both as an efficiency metric and as a signal of how quickly a security patch to a custom extension could realistically be deployed if needed.
Rollback frequency and duration
Tracking how often rollbacks are actually needed, and how long they take to execute, both indicating the overall health and reliability of the extension development and testing process.
A practical monitoring habit
Teams operating several custom extensions across a production Keycloak cluster often maintain a simple, centrally visible inventory tracking exactly which version of each extension is deployed on every node, refreshed automatically as part of the deployment pipeline itself, specifically so a version-consistency question can be answered in seconds during an incident rather than requiring someone to manually check each server individually.
9Design Patterns & Anti-patterns
Proven patterns
Immutable, versioned artifacts
Treat each built JAR as an immutable, uniquely versioned artifact — never overwritten or modified in place — so any deployed version can be unambiguously identified and, if needed, redeployed exactly as it was originally built.
Automated staging gate
Require every artifact to pass automated (and, where appropriate, manual) verification in staging before it becomes eligible for production deployment, with no informal bypass path.
Coordinated core-and-extension upgrade planning
Treat extension version compatibility as an explicit checklist item within any planned Keycloak core version upgrade, rather than assuming compatibility without verification.
One-command rollback capability
Build deployment automation specifically to support rolling back to the immediately prior artifact version quickly and reliably, treating this as a first-class capability rather than an afterthought.
Anti-patterns to avoid
Anti-pattern
- Manually copying JAR files to production servers without any version tracking or automated pipeline
- Skipping staging verification for “small, low-risk” changes, which are precisely the changes most likely to be under-tested
- Upgrading Keycloak’s core version without separately verifying custom extension compatibility against the new version
- Discovering, only during an actual incident, that no readily deployable previous version exists to roll back to
Instead, do this
- Use automated, versioned build and deployment tooling consistently, for every change regardless of perceived size
- Require staging verification as a non-negotiable gate before any production deployment
- Explicitly verify extension compatibility as part of every core version upgrade plan
- Always keep the previous, known-good artifact readily available for immediate rollback
10Best Practices & Common Mistakes
Best practices
Automate the entire pipeline end to end
Minimize manual steps between a code commit and a verified production deployment, reducing both effort and the chance of human error.
Document the deployment and rollback process clearly
Ensure the exact steps to deploy a new version, or roll back to a previous one, are written down and accessible, not held only in one engineer’s memory.
Test against a Keycloak version matching production exactly
Verify staging behavior against the same Keycloak core version actually running in production, since subtle SPI behavior differences can exist between versions.
Maintain a clear inventory of what’s deployed where
Keep an accurate, easily checked record of which extension versions are running across every node in the cluster at any given time.
Common mistakes
Treating custom extension deployment as a lightweight, informal process compared to core application deployments, despite the extension running with exactly the same trust and potential impact on the login system.
Not accounting for the build/augmentation step some Keycloak distributions require, leading to confusion when a correctly deployed JAR still doesn’t seem to be recognized by the running server.
Allowing cluster nodes to drift into inconsistent extension versions over time due to an incomplete or interrupted rollout, without any automated check to catch and flag this drift.
11Real-world & Industry Examples
Platform engineering teams
Organizations treating identity infrastructure as an internal platform build dedicated pipelines specifically for their custom Keycloak extensions, integrated with the same continuous delivery tooling used for their other core services.
Managed identity service providers
Companies operating Keycloak on behalf of many customers rely on rigorous, automated packaging and deployment discipline to safely roll out custom extension updates across a large, diverse fleet without disrupting any individual customer’s service.
Regulated industries with change-control requirements
Financial and healthcare organizations, often subject to formal change-management requirements, build deployment pipelines that naturally satisfy audit and approval requirements as a byproduct of the same discipline needed for reliable operation.
Organizations with many custom extensions
Companies that have grown to rely on several custom event listeners, required actions, and authenticators simultaneously find that a mature, shared deployment strategy across all of them prevents the operational chaos of managing each one differently.
A representative scenario
A platform engineering team supporting several internal product teams’ use of Keycloak had, over time, accumulated half a dozen custom extensions — event listeners, required actions, and a custom authenticator — each originally deployed through slightly different, ad hoc processes. After a deployment mistake caused a brief but disruptive authentication issue, the team consolidated everything into a single, shared build and deployment pipeline: every extension now goes through the same automated build, staging verification, and node-by-node production rollout process, with a consistent, centrally visible version inventory across the cluster. The next time a similar issue arose, from a genuine bug rather than a deployment mistake, the team was able to roll back the affected extension to its previous version within minutes, using the same well-tested rollback capability built into the shared pipeline.
12FAQ
13Summary and Key Takeaways
Key Takeaways
- SPI Packaging and Deployment Strategy is the engineering discipline that turns working custom Keycloak extension code into a reliably, repeatably deployed piece of production infrastructure.
- Packaging builds on Java’s standard service-provider discovery mechanism, with Keycloak scanning its providers directory at startup to find and register correctly packaged JARs.
- Modern, Quarkus-based Keycloak may require an explicit build/augmentation step for new providers to be fully recognized — not simply copying a file and restarting.
- A mature pipeline includes automated builds, versioned artifacts, staging verification, and controlled production rollout, coordinated with broader rolling upgrade discipline.
- Because custom code runs with the same trust as Keycloak’s own core, the entire pipeline — not just the extension’s own logic — deserves serious security scrutiny, including artifact integrity and dependency management.
- Version consistency across cluster nodes matters during steady-state operation, since mismatched versions can produce inconsistent behavior depending on which node serves a given request.
- Fast, reliable rollback capability — built on immutable, readily available prior artifacts — is what turns an inevitable bad deployment from a crisis into a routine, quickly resolved incident.
- Organizations running custom extensions seriously converge on treating this pipeline with the same engineering rigor given to any other critical production deployment process, not as a lightweight, informal afterthought.