Use Custom Infinispan Caches in Keycloak

June 2, 2026

Tags: #keycloak #infinispan #cache

When implementing custom Keycloak extensions (aka SPI implementations), the requirement to cache some data may arise from time to time. For example, you might want to cache the results of calls to external systems to reduce dependencies on those systems and speed up things during runtime.

As Keycloak already has a reliable cache implementation built in, which can also be distributed across your cluster, it is probably best to use this instead of an additional cache implementation. This is especially the case when it comes to cluster distribution. Fortunately, we can make use of the embedded Infinispan cache server to create custom caches during runtime (or at least during initialisation of an SPI implementation).

To add your custom cache to Keycloak’s cache manager, extend the DefaultCacheEmbeddedConfigProviderFactory class to implement the logic to add your custom cache (this class is explicitly meant for extension, see comment in the JavaDoc):

@AutoService(CacheEmbeddedConfigProviderFactory.class)
public class CustomCacheConfigProviderFactory extends DefaultCacheEmbeddedConfigProviderFactory {

  public static final String CACHE_NAME = "my-cache";

  @Override
  protected ConfigurationBuilderHolder createConfiguration(KeycloakSessionFactory factory) throws IOException {
    // create the default cache configuration
    ConfigurationBuilderHolder holder = super.createConfiguration(factory);
    // get the builder for the new custom cache
    ConfigurationBuilder builder = holder.newConfigurationBuilder(CACHE_NAME);
    // configure the cache mode, depending on if Keycloak runs in clustered mode or local
    boolean clustered = holder.getGlobalConfigurationBuilder().build().transport().transport() != null;
    if (clustered) {
      builder.clustering().cacheMode(CacheMode.DIST_SYNC).hash().numOwners(2);
    } else {
      builder.clustering().cacheMode(CacheMode.LOCAL);
    }
    // other settings like expiration and max entries
    builder.expiration().lifespan(4, TimeUnit.HOURS)
      .memory().maxCount(1000);
    // and return the whole configuration, containing our new custom cache
    return holder;
  }

  @Override
  public int order() {
    return super.order() + 10;
  }
}

Then, to actually use your custom cache in your desired Provider implementation, just do something like this:

Cache<String, String> cache = session.getProvider(InfinispanConnectionProvider.class)
  .getCache(CustomCacheConfigProviderFactory.CACHE_NAME);
String v = cache.computeIfAbsent("key", k -> "value");

And, voilà! You can now use custom caches within Keycloak for caching, without needing to add another caching solution such as Caffeine. Simply use the built-in options for your custom extensions. 😎

A note on Infinispan:
Infinispan is hardwired into Keycloak. Currently, it is not possible to replace Infinispan with a different cache implementation, nor is this planned at the time of writing this blog post. However, there are community approaches and extensions that allow you to replace Infinispan with different cache products. In my humble opinion, there is no real requirement to replace Infinispan at the moment. Yes, there were several flaws and problems with Infinispan in the past. However, a lot has changed, and when I say a lot, I really mean it! It's much more reliable and much faster than before! So, just use Infinispan! Don't try to replace it, as that will lead to other problems!

Du bist auf der Suche nach Keycloak Beratung, Unterstützung, Workshops oder Trainings?

Nimm Kontakt mit mir auf!

« Keycloak Account REST API OpenAPI Specification