Why Keycloak Logins Get Slow With Lots of Groups (and How to Fix It)

Guilliano Molaire Guilliano Molaire 12 min read

Last updated: July 2026

Slow Keycloak logins when users belong to many groups come from the cost of resolving group and role memberships and stamping them into the token on each authentication — heavy group/role protocol mappers, deeply nested groups, and LDAP group mappers that walk the directory all add up. The fixes: stop putting full group/role lists in the token, reduce nesting, tune or switch LDAP group mapping mode, and make sure realm/user caches aren’t being evicted.

Key Takeaways

  • Group and role resolution runs on every authentication, not once at user creation — the more groups, the more work per login.
  • Disabling or scoping down group/role protocol mappers is the single highest-impact fix; most tokens don’t need a full membership list.
  • LDAP group mapper mode matters: GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE is usually faster than LOAD_GROUPS_BY_MEMBER_ATTRIBUTE for large directories.
  • Infinispan user and realm caches reduce repeated database hits, but only if cache sizes are large enough and eviction isn’t constant.

What Happens During a Keycloak Login

Every Keycloak login or token issuance triggers a sequence of steps that most teams only think about once things go wrong. Understanding the sequence is the first step toward knowing where to look.

When a user authenticates, Keycloak loads the user record from its database (or from the LDAP/AD directory if federation is configured). It then loads all group memberships for that user, traverses the group hierarchy to collect any role mappings attached to those groups, collects directly assigned realm and client roles, and finally runs every protocol mapper configured on the client or the client scopes in play. Each mapper can read the user record, query group memberships, or make additional database calls — and the results are embedded in the access token and ID token before they’re signed and returned.

That pipeline runs for every token issuance: initial login, refresh, and in some flows even silent checks. With a small number of groups and a simple mapper set, the whole thing is fast. With hundreds of groups, nested hierarchies, and multiple role and group mappers all requesting the same membership data, latency climbs quickly.

The Keycloak server logs will show the slow path as increased time in the TOKEN_REQUEST or LOGIN event. If you enable DEBUG logging on org.keycloak.models.utils.ModelToRepresentation or org.keycloak.protocol.oidc.mappers, you’ll see mapper execution time per mapper on each request.

Why Group and Role Resolution Scales Poorly

The core problem is that group and role work isn’t amortized. Keycloak resolves memberships at runtime for each authentication event, not once at provisioning time. This design is correct for correctness — it means a group change is reflected immediately — but it means every login pays the full cost of membership resolution.

Nested groups multiply the work

Keycloak supports hierarchical groups. If a user belongs to /Engineering/Backend/Services, Keycloak must walk the path from leaf to root to collect roles assigned at each level. With three levels and ten role assignments spread across the hierarchy, that’s ten role-membership lookups per login. With twenty levels and hundreds of assignments, the number grows fast.

The “Full group path” mapper option makes this worse: instead of emitting just the leaf group name, it computes and emits the entire path string (e.g., /Engineering/Backend/Services) for each group the user belongs to. That traversal cost is paid for every group in the membership set.

Protocol mappers run on every token

The Group Membership mapper and the User Realm Role mapper are the two most common sources of latency. By default, the Group Membership mapper is included in the roles built-in client scope, and “Full Scope Allowed” is often left enabled on new clients. “Full Scope Allowed” instructs Keycloak to include every realm role the user has — directly and through groups — in the token. For a user in fifty groups that each carry ten roles, that’s potentially five hundred role objects to resolve, deduplicate, and serialize into the token.

The Keycloak documentation on group mappers and LDAP federation describes how these mappers are configured, but doesn’t always surface the performance implications clearly. The short version: every mapper you leave active runs for every token, even if the receiving application never reads the claim.

LDAP group mapper modes have very different costs

When Keycloak federates users from LDAP or Active Directory, group membership can be loaded in two ways, controlled by the “Mode” field on the LDAP Group Mapper:

  • LOAD_GROUPS_BY_MEMBER_ATTRIBUTE — Keycloak queries the LDAP directory for all groups that contain the user’s DN in their member attribute. For a directory with thousands of groups, this is a broad search across the entire groups subtree. Performance depends heavily on whether the LDAP server has an index on the member attribute, and many AD deployments do not have that index optimized for reverse lookup.

  • GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE — Keycloak reads the memberOf attribute directly from the user object. Active Directory populates memberOf automatically and it’s indexed per-user, making this lookup faster in most cases. The tradeoff is that nested group membership isn’t always fully expanded in memberOf depending on the AD configuration.

Switching from LOAD_GROUPS_BY_MEMBER_ATTRIBUTE to GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE is one of the highest-impact LDAP-specific changes you can make. See the full LDAP integration walkthrough for how to configure federation from scratch.

Symptom, Cause, and Fix at a Glance

Before going deep on each fix, this table maps the most common symptoms to their root cause and the corresponding remedy:

Symptom Likely Cause Fix
Login takes 2-10 seconds for users with many groups Group Membership mapper running with Full group path enabled Disable mapper or remove Full group path
Token issuance slow for users with many realm roles Full Scope Allowed enabled on client Disable Full Scope Allowed; assign only needed scopes
LDAP-federated login slow for users in many AD groups LOAD_GROUPS_BY_MEMBER_ATTRIBUTE with unindexed LDAP Switch to GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE
Login slow on first request after idle, fast afterward Infinispan user cache evicted Increase cache size or reduce max-count to avoid eviction
Slow logins only for deeply nested groups Nested group role traversal Flatten group hierarchy; avoid roles assigned at intermediate levels
All logins slow regardless of group count Database connection pool exhaustion Tune pool size and query timeouts; see PostgreSQL tuning guide

Fix 1: Stop Emitting Large Group and Role Claims

This is the change with the highest return for the least effort. Most applications don’t read the groups or roles claim from the access token at all — they either use the token for authentication only or query a separate API for authorization data. If that describes your setup, you’re paying the full cost of group resolution for zero benefit.

The pattern we see most often in production Keycloak deployments: the Group Membership mapper and User Realm Role mapper are both enabled on the global roles scope, every client inherits that scope by default, and nobody has ever removed them because the assumption is “they must be needed.” Audit your clients first. Most of the time, the fix is removing or disabling those mappers from the optional or default client scopes, not writing any code.

To audit, go to Clients → select the client → Client Scopes → look for the roles scope in the “Default Client Scopes” list. Click through to the mappers tab. Disable “Group Membership” and “User Realm Role” if the application doesn’t need them in the token.

If some applications do need group or role data, use a dedicated client scope and assign it only to those clients. The guide to client scopes versus roles covers how to structure this cleanly. The principle is the same as the principle of least privilege: don’t put data in a token that the recipient doesn’t need.

For applications that need group membership data occasionally (not on every request), consider fetching it from the UserInfo endpoint on demand rather than including it in every access token. The UserInfo endpoint can carry the same claims but the application calls it only when it needs to check membership, not on every API request.

Fix 2: Reduce Group Nesting and Membership Cardinality

If you’ve scoped down your mappers and logins are still slow, the next step is to look at the group hierarchy itself. Keycloak’s group traversal is depth-first and synchronous — each level of nesting adds latency.

A few structural changes help significantly:

  • Flatten where possible. If you have /Engineering/Backend/Services/Platform, consider whether three intermediate nodes are necessary or whether one top-level /Platform group is sufficient.
  • Assign roles at leaf groups only. Roles assigned at intermediate nodes in the hierarchy are collected during traversal for every descendant user. This means a role on /Engineering is resolved for every user in every subgroup under Engineering, on every login.
  • Remove stale memberships. Users accumulate group memberships over time — especially in LDAP-federated environments where group cleanup is manual. A user in fifty groups where they’re actively working in five is paying the resolution cost of fifty.

These are organizational changes that take longer to execute than configuration changes, but they have lasting effect. Short-term, fix the mappers. Long-term, design the group hierarchy with authentication cost in mind.

Fix 3: Tune the LDAP Group Mapper Mode

If your users come from Active Directory or another LDAP directory, the LDAP Group Mapper configuration deserves close attention. The relevant setting is in User Federation → your LDAP provider → Mappers → the group mapper → “Mode.”

Switch to GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE if you’re using AD. Configure the “Member-Of LDAP Attribute” field to memberOf (the default for AD). This tells Keycloak to read the pre-computed memberOf attribute from the user object rather than running a reverse-search across all groups.

One caveat: AD’s memberOf attribute by default contains only directly assigned groups, not nested group memberships (unless you’ve enabled the msDS-MemberTransitiveOf attribute or your AD functional level supports it). If your authorization model relies on inherited membership through nested AD groups, test carefully before switching modes — you may need to flatten AD group nesting in parallel.

Also check the “User Groups Retrieve Strategy” and the search filter on the LDAP Group Mapper. A broad search base combined with a wide (objectClass=group) filter will pull every group in the directory before filtering — on large AD forests this is expensive. Scope the search base to the OU that contains your application groups.

For detailed LDAP configuration steps and common AD gotchas, the Keycloak LDAP integration guide covers connection pooling, bind account permissions, and sync scheduling.

Fix 4: Tune Infinispan Caches to Reduce Eviction

Keycloak uses Infinispan as its embedded distributed cache for user sessions, realm configuration, and user data. In Keycloak 26.x, the user cache (users) and the realm cache (realms) are both bounded by a max-count setting. When the cache is full, entries are evicted under an LRU-like policy. An evicted user entry means the next request for that user must hit the database again — and for an LDAP-federated user, that may mean a round-trip to the directory server as well.

In clusters under load, we’ve observed that the default cache sizes in Keycloak’s reference configuration are sized conservatively. If your realm has 50,000 users and your max-count for the users cache is 10,000, the cache will be in constant churn. Every login for an evicted user pays the full load-from-database cost, which includes group membership loading.

To check current cache behavior, use the Keycloak Admin REST API: GET /admin/realms/{realm}/cache/users will show the current cache statistics in some builds. More reliably, expose the Infinispan metrics endpoint (/metrics or the JMX endpoint, depending on your deployment) and watch cache_entries and evictions over time.

To increase cache capacity, edit your Keycloak configuration (typically conf/keycloak.conf or the Infinispan XML embedded in the server distribution):

<local-cache name="users">
  <memory max-count="50000"/>
</local-cache>

Adjust max-count based on your active user count and available heap. A rough starting point is 2x your peak concurrent user count. If you’re running a cluster, remember that each node has its own cache and the user cache is not replicated by default in the embedded configuration — each node will warm its own cache independently.

The cluster configuration best practices guide covers Infinispan tuning in the context of multi-node deployments, including replicated versus distributed cache modes.

Fix 5: Consider Attribute-Based Authorization

Groups are a blunt instrument when taken to large scale. Every group a user belongs to carries a token resolution cost. If your authorization model has grown organically — where groups are created for every permission combination — you may have hundreds of groups doing the work that a handful of user attributes could handle more cleanly.

Keycloak supports user attributes (arbitrary key-value pairs on the user record) that can be mapped into tokens via the User Attribute mapper. Reading one attribute from the user object is a single database read — no traversal, no hierarchy, no LDAP group search. For fine-grained permissions that don’t require group-level inheritance, an attribute like subscription_tier=enterprise or department=finance can replace a group membership entirely.

This isn’t a silver bullet. Groups are still the right model for team-level resource sharing, RBAC role inheritance, and cases where membership needs to be managed through a directory. But for access control that’s really about a property of the individual user rather than their organizational membership, attributes are both faster to resolve and easier to reason about.

The JWT token lifecycle guide is worth reading alongside this section — understanding how token expiry and refresh interact with group-resolution cost helps you design a caching strategy at the token level too, not just at the Keycloak cache level.

When to Look at the Database

If you’ve applied all of the above and logins are still slow, the bottleneck may have moved downstream to the database. Keycloak stores group-to-role mappings, user-to-group mappings, and user attributes in PostgreSQL (or MySQL/MariaDB). Queries against the USER_GROUP_MEMBERSHIP, GROUP_ROLE_MAPPING, and KEYCLOAK_ROLE tables can become slow at scale without proper indexes.

The PostgreSQL tuning guide for Keycloak covers the specific indexes, connection pool sizing, and query plan analysis that matter for authentication workloads. Check that index on USER_GROUP_MEMBERSHIP(USER_ID) in particular — it’s the join that powers every group membership lookup.

Frequently Asked Questions

Why is my Keycloak login slow?

Slow Keycloak logins are most often caused by one of three things: protocol mappers resolving large numbers of groups or roles on every token issuance, LDAP group lookups that scan large directory subtrees, or Infinispan cache eviction forcing repeated database reads. Start by disabling unnecessary group and role mappers, then check your LDAP group mapper mode, then look at cache sizing. The symptom-cause-fix table in this post maps common patterns to their remedies.

Do many groups slow down Keycloak?

Yes. Group membership resolution in Keycloak runs at authentication time, not at provisioning time. A user in 200 groups costs roughly 200 times more group-resolution work than a user in 1 group, and deeply nested groups multiply that cost further. The Group Membership protocol mapper and the User Realm Role mapper with Full Scope Allowed are the two most common sources of group-induced slowness. Disabling or scoping them down is the highest-impact fix.

How do I speed up Keycloak token issuance?

The fastest wins are on the protocol mapper side: audit which mappers are enabled on your clients’ default client scopes, remove Group Membership and User Realm Role mappers from clients that don’t need them in the token, and disable “Full Scope Allowed” on those clients. If you’re using LDAP federation, switch to GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE mode on the LDAP Group Mapper. For background on how client scopes interact with token content, see the client scopes versus roles guide.

How does LDAP group mapper mode affect login performance?

The LOAD_GROUPS_BY_MEMBER_ATTRIBUTE mode performs a reverse-search across all groups in the LDAP subtree to find which groups contain the user’s DN. On large directories this is expensive, especially without a member attribute index. The GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE mode reads the memberOf attribute directly from the user object — a single indexed attribute read. Switching modes is one of the highest-impact changes for AD-federated Keycloak deployments. See the LDAP integration guide for step-by-step configuration.

Will increasing Keycloak’s Infinispan cache size help with login speed?

It can, yes — but it depends on whether cache eviction is actually happening. If your max-count is lower than your active user count, entries are constantly evicted and every login for an evicted user pays a full database round-trip. Increasing max-count reduces eviction and keeps warm user records (including their group memberships) in memory. Check eviction metrics before and after the change to confirm it’s having effect. Cache sizing is covered in detail in the cluster configuration best practices guide.


If diagnosing and tuning Keycloak performance in production sounds like work you’d rather not own, Skycloak’s managed Keycloak hosting handles the configuration, cache tuning, LDAP mapper optimization, and infrastructure sizing for you — so your team focuses on your application, not on Keycloak internals.

Tired of running Keycloak yourself?

Skycloak runs real upstream Keycloak for you with a 99.99% SLA. No fork, no lock-in, just managed Keycloak that stays patched and on call so you don't have to.

Guilliano Molaire
Written by
Founder

Guilliano is the founder of Skycloak and a cloud infrastructure specialist with deep expertise in product development and scaling SaaS products. He discovered Keycloak while consulting on enterprise IAM and built Skycloak to make managed Keycloak accessible to teams of every size.

Start Free Trial Talk to Sales
© 2026 Skycloak. All Rights Reserved. Design by Yasser Soliman