Limits

Values for heyidentity.dev · last updated October 2026

What the hosted service limits, how much each plan allows, and how to tell one rejection from another. Self-hosted or staging deployments can use other values.

Runtime limits per source

Every protocol endpoint limits requests per source. These limits protect the service from floods and are the same on every plan. A request over its limit is rejected with HTTP 429 and a Retry-After header.

Requests per source and window, by endpoint
EndpointLimit per source
Authorize, end session and the pinned user page (one shared limit)300 per minute
User selection page (the page and its form post)600 per minute
Token600 per minute
Discovery300 per minute
JWKS300 per minute
Userinfo300 per minute

A sign-in makes one authorize request, plus two user selection page requests when the user picker is shown. The selection page has its own limit, so one source can complete as many fresh sign-ins as its authorize limit allows, 300 per minute, with the user picker or with a single-user configuration.

What counts as a source

A source is one IPv4 address or one IPv6 /64. Clients behind a shared egress address, such as a NAT or shared CI runners, share a source and its limits.

The address is the one of the client that connects to HeyIdentity, as the edge proxy forwards it. For authorize, the user selection page, end session and the pinned user page that is the browser of the person signing in. For token, discovery, JWKS and userinfo it is the server or CI runner that calls the endpoint, so a test suite's token requests all count against the runner's address.

Token requests per client

The token endpoint also limits requests per client_id: 4000 per minute, whatever the source. It applies to a client_id sent in the request body. It is checked after the per-source limit, so a request can be rejected by either. It sits above what any tenant tier can issue in a minute, so a tenant with its own client_id reaches its tenant limit first.

Tenant tiers

Each tenant has one tier. It decides how many configurations, clients and users the tenant may hold, how large a configuration document may be, and how many sign-in and token requests the whole tenant may make.

Limits by tenant tier
LimitUnverifiedFreeProEnterprise
Configurations per tenant 1 5 20 50
Clients per configuration 3 5 20 50
Users per configuration 10 20 100 250
Configuration document size 32 KB 64 KB 256 KB 256 KB
Token issuance per tenant (sustained) 20 per minute 120 per minute 300 per minute 1200 per minute
Token issuance burst 20 120 600 2400
Fresh sign-ins (sustained) 10 per minute 60 per minute 150 per minute 600 per minute
Session pinning Not included Not included Included Included
Tenant lifetime 7 days if agent-created, 30 days for an unconfirmed sign-up No expiry No expiry No expiry

Enterprise values are the starting values of a tier HeyIdentity grants on request. Every Enterprise tenant gets the same values; they may be raised, and they are not lowered while a grant is active. Tenants created by HeyIdentity staff get the Pro limits. A configuration with one user never shows a user picker, on every plan.

What counts toward token issuance

Every authorize request and every token request counts, refresh requests included, and so does a request that is later rejected for another reason. The user selection page does not count. A fresh sign-in uses two (one authorize and one token request) and each refresh one more, so the sustained rate allows half as many fresh sign-ins. The allowance belongs to the tenant, not to a source or a client.

A tenant that has been quiet can use its whole burst at once, for example when every worker of a CI run signs in at the start. After that its allowance refills at the sustained rate, in steps of at most a second, up to the burst again.

At an item maximum

At the maximum of configurations, clients or users, the Agent API answers 400 usage_limit_exceeded naming the limit, and the owner editor disables Add with a short explanation. Items above a maximum, for example after Pro ends, keep working and stay editable. You just can't add more until you are below it.

Windows and retries

Per-source and per-client_id windows are fixed: the count starts at zero again when the window ends, not a window after your first request. The tenant's allowance refills in small steps instead.

Every runtime and Agent API rejection carries Retry-After in seconds. For a fixed window it is at most the window length, for the tenant limit at most one refill step. A client that waits that long finds the limit open again. Nothing retries a rejected sign-in for you, see running CI.

Telling rejections apart

A rejected request gets HTTP 429 and a Retry-After header. The error and the start of the error_description say which limit it was. The per-tenant rejection also carries an error_uri that links how to get more room.

Rejections by limit
LimitEndpointHTTP statuserrorerror_description starts with
Per source Authorize, end session 429 slow_down Too many requests from this source.
Per source Token 429 slow_down Too many requests from this source.
Per client_id Token 429 slow_down Too many token requests for this client_id.
Per tenant (token issuance) Authorize, token 429 slow_down, with error_uri Too many authorize/token requests for this tenant.
Per source User selection page, pinned user page, discovery, JWKS, userinfo 429 None: the response has no body None

Agent API limits

The Agent API has its own limits. A source is defined as above.

Agent API limits
LimitValue
Tenant creations per source10 per hour
Tenant creations overall100 per hour
Unclaimed tenants alive at once2000
Calls per source120 per minute
Calls per agent token60 per minute
Active agent tokens per tenant10
Claimed tenants per email address10

How to ask for higher limits

  1. An unverified tenant is claimed and its email verified: it gets the Free limits.
  2. A Free tenant activates Pro on its management page.
  3. A tenant that needs more than Pro asks for Enterprise.

Enterprise raises the tenant's total across several sources. A single source stays at the per-source limits on every plan: up to 300 per minute fresh sign-ins by its authorize limit, and 600 per minute token requests by its token limit, which is half of Enterprise's sustained rate of 1200 per minute. So one runner behind one address gains nothing from Enterprise over Pro's burst.

To ask, email support@heyidentity.dev with your tenant route id, the sign-ins and refreshes per minute you expect, and how many runners or egress addresses your tests use.

The tenant route id is shown with a Copy button at the top of your management page. It is also the part after /t/ in your authority URL.

Enterprise is granted for a fixed period. The values above are starting values: a later grant period may come with higher ones, and active grants are never lowered.

Questions

Why do I get a 429 or slow_down?

One of the limits above was used up. Compare the response with the rejections table, and wait the seconds its Retry-After header gives before you try again. A per-source rejection means the address your requests come from sent too many requests to that endpoint in the window. A per-tenant rejection means all sign-ins and token requests of the tenant did.

How do I run a large CI suite within the limits?

Nothing retries a rejected sign-in automatically. A browser sign-in that gets a 429 shows an error page, and MSAL and Microsoft.Identity.Web throw instead of waiting. So a suite that runs past its tier's allowance fails, unless it retries on Retry-After itself. How a suite gets its tokens decides which plan it fits:

Token reuse and the plan it fits
How tests get tokensFits
One sign-in per test user, reused for the whole run (for example Playwright storage state, or a cached token)Free
One sign-in per test class or fixturePro, within its burst of 600
A fresh sign-in or token request per testNot recommended on any plan. From one runner it is stopped by the per-source limits, which no plan raises.

Do the limits apply per source, per client or per tenant?

All three, to different things. Requests are limited per source on every protocol endpoint. Token requests are also limited per client_id. Sign-in and token requests count against the tenant's token issuance allowance, and the number of items a tenant may hold depends on its tier.

How do I get more room?