Affected: All client-side SDKs
Overview
When you see a spike or unexpectedly high Client-side Monthly Active Users (cMAU), the root cause is almost always how contexts are generated and evaluated by client-side and mobile SDKs, not a change to LaunchDarkly's billing rules or product.
This article explains:
- How cMAU is calculated and how that differs from what you see in the UI.
- How to use Plan usage, Diagnostic usage, and the Contexts list to investigate.
- How to use the Contexts REST API when you need a full export.
- Common patterns that inflate cMAU and concrete guardrails to avoid them.
Solution
Confirm how cMAU is billed compared to what you see in the UI
Before debugging numbers, align on these core definitions:
cMAU, the billing metric
- LaunchDarkly bills on the number of unique context keys seen for the single primary context kind. The primary kind is the kind with the highest number of unique keys in that month. This is often
user, but it could be another kind likedeviceoraccount. - Only client-side, mobile, and edge SDK evaluations count toward cMAU. Server-side evaluations are billed through service connections, not MAU.
Plan usage
- Shows cMAU at the account level against your plan limit.
- The Client-side MAU view can break down usage by project and environment, but a given context key evaluated in multiple projects still counts once at the account level.
Diagnostic usage
- Shows overall context activity across all projects and environments, including both server-side and client-side contexts and all context kinds, for example
user,device,organization, and custom kinds. - Best used to break down which SDKs, application IDs, context kinds, and attributes are driving traffic.
Contexts list, per environment
- Lists contexts on a rolling 30-day basis. Each identify or evaluation event refreshes that 30-day window. Contexts disappear if they are not seen for 30 days or if they are explicitly removed.
- This 30-day window differs from the monthly cMAU calculation. A context can be visible in the list for part of the next month without contributing to that month's cMAU if it isn't evaluated again.
Key implications:
- Seeing a large number of contexts in the Contexts list does not necessarily mean you are billed for all of them in the current month.
- Seeing high numbers in Diagnostic usage can reflect server-side traffic and multiple context kinds. The billing decision is made only from the highest-volume context kind evaluated by client-side SDKs.
Use Plan usage to confirm whether there is a real cMAU problem
- Click the gear icon in the left sidenav to view Organization settings.
- Choose Plan usage, then Client-side MAU.
Review the following:
- Account-level cMAU against your plan allowance.
- The per-project breakdown, to identify which projects and environments contribute most.
Confirm the following:
- Whether the account-level cMAU is significantly higher than your own expectation of active users, for example a cMAU larger than your total number of end users.
- Whether the spike coincided with any of these events:
- SDK upgrades, especially client-side SDK major versions.
- New client apps or platforms.
- Experiments or broad rollouts on unauthenticated traffic.
If the account-level cMAU looks roughly correct, the issue may just be per-project visualization, for example the same contexts appearing in multiple project charts. If the account-level number itself is clearly wrong, continue with deeper diagnosis.
Use Diagnostic usage to localize the spike
- Click the gear icon in the left sidenav to view Organization settings.
- Choose Diagnostic usage and start with the Client-side contexts view.
- Set an appropriate time range. Use three-month windows to identify step changes around a particular period, for example an SDK upgrade or experiment launch.
- Use Dimensions to slice the data:
-
Context Kind: confirm which kind, typically
user, is the primary driver of cMAU. This is usually what you are billed on. - SDK Name: identify which SDK families, such as JS, React, React Native, or Flutter, are generating most client-side evaluations.
- SDK App ID: once application metadata is configured in your SDKs, this lets you correlate usage to specific apps or app versions.
- Dimensions related to anonymity, where available, that separate anonymous from non-anonymous context usage.
-
Context Kind: confirm which kind, typically
- Compare data before and after the spike date. Look for context kinds, SDKs, or applications that rose sharply during the spike window and stayed elevated afterward.
This often reveals whether the issue is limited to one mobile app, a particular web client, or a new context kind introduced by an implementation change, for example device or brand_region.
If most of the cMAU is coming from a single project, environment, and client-side SDK pair, for example a React Native app in production, focus on that environment in the next steps.
Check anonymous contexts and key stability
Anonymous contexts and unstable keys are a common cause of unexpected cMAU.
Understand how anonymous contexts affect cMAU
If you send a single, stable anonymous context key to each anonymous end user and reuse it for that user, then each anonymous user contributes one cMAU for the entire calendar month for that context kind:
{
"kind": "user",
"key": "anon-web-user-key",
"anonymous": true
}If instead you let the SDK auto-generate a new random key for each anonymous visitor or session, many JavaScript-family client-side SDKs generate a unique key per load or session, and each unique key counts separately toward cMAU:
{
"kind": "user",
"anonymous": true
}Follow these best practices:
- Set an explicit, stable key for each anonymous context and mark it
anonymous: true. - Store anonymous keys in persistent storage, for example localStorage, AsyncStorage, or secure storage, and reuse them across sessions.
- Avoid generating new anonymous keys per page load, per device reinstall, or per request.
Use Diagnostic usage to view the anonymous contribution
- Click the gear icon in the left sidenav to view Organization settings.
- Choose Diagnostic usage and start with the Client-side contexts view.
- Use the All dimension drop-down to separate anonymous from non-anonymous contexts.
This helps confirm whether an unexpected spike is due to anonymous key generation or identified users. If anonymous contexts are minimal and most cMAU is coming from non-anonymous user contexts, the problem is more likely in how you generate user keys than in anonymous inflation.
Investigate context keys and kinds in the Contexts list
Once you have localized the problem project and environment:
- Click the project dropdown. The project menu appears. Select the project.
- Go to Contexts, located under Features, and select the environment.
- Use the Filter tool to inspect stored contexts and filter by context kind. Start with the kind that Diagnostic usage shows as primary, for example
user. - Check whether the number of contexts over 30 days is broadly in line with your expectations.
- Inspect key patterns. Look for:
- Multiple key formats for what should be the same logical entity, for example
2488448andorg:142835for the same organization. Each distinct key counts separately. - Keys that appear to be session IDs, device IDs, or other high-cardinality tokens that are not intended to represent unique users.
- Unexpected context kinds, for example
brand_region,app, ordevice, that might have more unique keys thanuserand could become the primary billed context kind if their volume surpassesuser.
- Multiple key formats for what should be the same logical entity, for example
- Clarify key semantics with your own systems. Confirm that the value you use as
context.keyfor theuserkind, for exampleorgPersonId,user_id, or an email hash, lines up with how you define a unique person in your customer relationship management (CRM) system or other database. If a single real person can have multiple keys, for example multiple organization memberships or multiple unrelated IDs, your expected cMAU must reflect that reality.
Keep in mind:
- The Contexts list includes contexts created by both server-side and client-side SDKs. When debugging cMAU, look for attributes like
appId,appName, or custom source fields that let you distinguish client-side traffic from server-side traffic in the same environment. - The Contexts list only shows non-anonymous contexts.
- In high-volume environments, contexts are sampled.
Use the Contexts REST API for large-scale comparison
For deeper analysis, consider using the Search contexts API:
GET /api/v2/projects/{projectKey}/environments/{envKey}/contexts/searchA typical workflow looks like this:
- Export expected identities from your source of truth, for example all expected user IDs from your CRM for the relevant month.
- Iterate through LaunchDarkly contexts:
- Call Search contexts for the environment, filtering to the primary context kind, for example
kind=user. - Use the continuation token or next link from the API to paginate through all results.
- Respect LaunchDarkly REST API rate limits. Back off and retry after
429responses.
- Call Search contexts for the environment, filtering to the primary context kind, for example
- Diff the two datasets:
- Identify keys that appear in LaunchDarkly but not in your CRM or other database. These are potential unexpected contexts.
- Optionally, log or export each key plus useful attributes, for example
orgId,appId,appVersion, anddeviceType, so you can group and investigate patterns, such as all extraneous keys coming from a particular app or device type.
This programmatic comparison can be a lengthy process, but it can confirm whether a perceived overage is due to extra keys LaunchDarkly is seeing or misaligned expectations about how many distinct contexts actually exist.
Common root causes and how to diagnose them
The following patterns appear repeatedly in this problem space.
Anonymous inflation from per-visitor or per-session anonymous keys
Symptoms:
- Large number of anonymous contexts in Diagnostic usage.
- cMAU much higher than the context count from the UI or API, especially on web or mobile products with substantial anonymous traffic.
Diagnosis:
- In Diagnostic usage, group by anonymous to determine whether anonymous contexts are significant contributors.
Fixes:
- Set a stable, persisted key for each anonymous user, as described earlier in this article. A shared key between anonymous contexts is generally not recommended. To learn more, read Anonymous contexts.
- Avoid relying on SDK-generated random keys unless you deliberately want each session counted as a separate MAU.
Multiple context keys per real user
Symptoms:
- cMAU significantly exceeds the total user count in your CRM or other database, for example 1.1 million user contexts compared to roughly 600,000 identities.
- The Contexts list shows multiple user keys that map back to the same real person, for example per-organization keys, per-device keys, test users, or stale IDs.
Diagnosis:
- In the Contexts list, search for specific identifiers and compare multiple keys that share an attribute, for example the same
orgIdbut different keys. - Use the REST API diff approach described in the previous section to identify which LaunchDarkly keys do not exist in your CRM or other database, or the reverse.
Fixes:
- Decide on a single canonical user key, for example an internal person ID, and ensure all client-side SDKs use that key consistently across apps and organizations.
- If you need organization-level targeting, consider using separate context kinds, for example
organization, instead of encoding that into multiple user keys. - Clean up legacy or experimental key formats that are no longer needed.
Multi-project or micro-frontend architectures
Symptoms:
- Multiple projects and environments share the same underlying users.
- Per-project charts show significant usage in several projects, and it's unclear whether those users are being billed once or multiple times.
Diagnosis:
- Remember that account-level cMAU is deduplicated by context kind and key across projects. The same context evaluated in multiple projects counts once for billing, even if it appears in multiple project charts.
- Use the Contexts list and the Search contexts API to verify that the same keys are present in multiple projects and that some projects aren't using slightly different key formats or context kinds.
Fixes:
- Make sure every client-side SDK in every project uses the same context kind and key semantics for the same logical user.
- Avoid accidental context kind drift, for example
usercompared toprofileoraccount, that could change which kind becomes primary in a given month.
SDK upgrades or implementation changes
Symptoms:
- A clear step change in cMAU or client-side context counts around the time of an SDK upgrade or refactor.
Diagnosis:
- Use Diagnostic usage to confirm when the step occurred and which SDKs were involved.
- Check SDK changelogs and migration guides for breaking changes in how contexts are configured, especially when moving from user-only to multi-context APIs.
Fixes:
- Validate that you are still passing a stable key for each context kind.
- Validate that you are not inadvertently making more frequent
identify()calls with new keys per session or per device. - When adopting multi-contexts, ensure you understand which kind you expect to be primary, and keep high-cardinality kinds, for example per-device kinds, under control so they don't unintentionally become the billed kind.
Follow implementation guardrails to keep cMAU predictable
The following practices help prevent unexpected cMAU growth:
Use stable, meaningful keys
- Choose keys that map directly to how you define unique users, or other primary entities, in your system.
- Avoid session IDs, request IDs, or other high-cardinality tokens as keys.
- Treat every new distinct key as counting as at most one cMAU per month for that kind.
Be deliberate with context kinds
- Decide which context kind, usually
user, you expect to dominate monthly volume. - Keep other kinds, for example
device,brand_region, orapp, from exploding in cardinality so they don't overtakeuseras the primary billed kind.
Configure anonymous behavior explicitly
- Avoid an implementation that relies on SDK-generated anonymous keys for high-frequency sessions.
Use application metadata in SDKs
- Configure
application.idandapplication.versionin your client-side SDKs so you can break down Diagnostic usage by app and quickly identify which app is responsible for spikes.
Tie LaunchDarkly contexts back to your own metrics
- Periodically run a Search contexts export and compare it to your CRM, other database, or product analytics to ensure that LaunchDarkly is seeing roughly the same volume of unique users. Remember to account for anonymous contexts, which don't appear in the Contexts list.