Skip to content

AcquireTokenForClient becomes extremely slow with 164K tokens in one app-token cache partition #3961

Description

@ararbi90

Microsoft.Identity.Web Library

Microsoft.Identity.Web

Microsoft.Identity.Web version

Microsoft.Identity.Client: 4.74.1

Web app

Sign-in users and call web APIs

Web API

Protected web APIs (validating tokens)

Token cache serialization

In-memory caches

Description

Description

We operate a token broker that uses  Microsoft.Identity.Web  and MSAL to acquire application tokens for many downstream audiences. Requests commonly share the same broker client and tenant, creating a high-cardinality workload within one app-token cache partition.

During an outage, MSAL reported:

[FindAccessTokenAsync] Discovered 164663 access tokens in cache using partition key:
{clientId}_{tenantId}_AppTokenCache

For the same operation:

DurationInHttpInMs: 977
DurationTotalInMs: 1980434

The identity-provider request completed in approximately one second, but the overall token acquisition took approximately 33 minutes. Inbound token validation also completed quickly.

Our current hypothesis is that the delay occurred during local MSAL cache processing—such as partition lookup, filtering, overlap removal, or cache update—rather than during inbound validation or the token endpoint request.

Workload

The broker calls:

ITokenAcquirer.GetTokenForAppAsync(scope)

This delegates to MSAL  AcquireTokenForClient . The same broker client and tenant acquire tokens for many downstream scopes or audiences, allowing many access-token entries to accumulate under one app-token partition.

Versions observed during the incident:

Microsoft.Identity.Web: 4.7.0
Microsoft.Identity.Client: 4.74.1

Reproduction steps

If you have a large partition that will eventually happen

Error message

There is not error message the call eventually is processed but it takes 30 minutes to request a token.

Id Web logs

No response

Relevant code snippets

Relevant code paths

ITokenAcquirer.GetTokenForAppAsync
→ MSAL AcquireTokenForClient
→ ClientCredentialRequest.GetCachedAccessTokenAsync
→ TokenCache.FindAccessTokenAsync
→ Accessor.GetAllAccessTokens(partitionKey)
→ filter tokens by scope and request properties

When refreshing a token:

TokenCache.SaveTokenResponseAsync
→ cache synchronization
→ DeleteAccessTokensWithIntersectingScopes
→ Accessor.SaveAccessToken

Key references:

• Microsoft.Identity.Web app-token acquisition
• MSAL cache lookup and filtering
• MSAL app-token partition key
• MSAL cache save and synchronization
• Overlapping-token removal

Regression

No response

Expected behavior

We should be able to get a token in a reasonable time

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions