Technical Advisory 10018
Date and Version
Versions: >= v4.20.0
Date: 2026-10-12
Description
The list endpoints of the ZITADEL APIs support pagination through the limit and offset of their query.
The number of returned results is controlled by two runtime settings:
SystemDefaults.DefaultQueryLimit(default100): the limit applied if a request does not specify one.SystemDefaults.MaxQueryLimit(default1000): the highest limit a request may specify.
Several list endpoints did not apply these settings.
A request without a limit returned all matching results, and a request with a higher limit than allowed was not rejected.
This contradicts the API documentation and can cause expensive database queries on large instances.
For the v1 APIs, this is a regression: they previously applied a default and maximum limit of 1000 (configured by SearchLimit), which was lost during a refactoring.
Starting with v4.20.0, the limits are enforced on all list endpoints.
Impact
v2 APIs
The following endpoints now behave like all other v2 list endpoints:
zitadel.user.v2.UserService.ListUsers(and v2beta)zitadel.user.v2.UserService.ListIDPLinkszitadel.org.v2.OrganizationService.ListOrganizationszitadel.session.v2.SessionService.ListSessions(and v2beta)zitadel.instance.v2.InstanceService.ListInstances,ListCustomDomainsandListTrustedDomains(and v2beta)zitadel.app.v2beta.AppService.ListApplicationsandListApplicationKeys
Requests without a limit return at most DefaultQueryLimit (100) results.
Requests with a limit greater than MaxQueryLimit (1000) fail with an InvalidArgument error.
Additionally, ListSessions and ListOrganizations (v2 and v2beta) requests without a sorting column now return the results sorted by ID (descending by default) instead of in an undefined order, so they can be paginated reliably.
v1 APIs
All list endpoints of the Admin, Auth, Management and System APIs, including the change endpoints (e.g. ListUserChanges), are affected.
Requests without a limit return at most MaxQueryLimit (1000) results, as they did before the regression.
Requests with a limit greater than MaxQueryLimit fail with an InvalidArgument error.
The Auth.SearchLimit and Admin.SearchLimit configuration options are removed.
Admin.SearchLimit had no effect.
Auth.SearchLimit only limited the refresh tokens listed by ListMyRefreshTokens and revoked by RevokeAllMyRefreshTokens, which are now limited by MaxQueryLimit.
The events API (zitadel.admin.v1.AdminService.ListEvents) is not affected: it keeps its own maximum of 1000 events and silently caps higher limits, independent of MaxQueryLimit.
Who is affected
Clients that call one of the endpoints above:
- without a
limitand expect to receive all results. They now silently receive only the first page of results. - with a
limitgreater thanMaxQueryLimit(1000). Their requests now fail with anInvalidArgumenterror instead of returning the requested number of results.
Mitigation
Paginate the requests:
- Set the
limitof the query to the page size (at most 1000). - Increase the
offsetby the page size for each subsequent request. - Stop when the number of received results reaches the
total_resultin thedetailsof the response.
To detect requests without a limit that are affected, compare the number of returned results with the total_result in the details of the response.
Requests with a limit that is too high fail with an InvalidArgument error with the message Limit exceeded (ID QUERY-4M0fs).
If you are running ZITADEL self-hosted and need time to update your clients, you can adjust the limits:
- Raise
MaxQueryLimit(ZITADEL_SYSTEMDEFAULTS_MAXQUERYLIMIT) to the highestlimityour clients request. On the v1 APIs, this also raises the number of results returned to requests without alimit. - Restore the previous behavior by setting
DefaultQueryLimitand / orMaxQueryLimitto0(ZITADEL_SYSTEMDEFAULTS_DEFAULTQUERYLIMIT/ZITADEL_SYSTEMDEFAULTS_MAXQUERYLIMIT).
Note that these settings apply to all list endpoints, including the ones that enforced the limits already. Disabling the limits is not recommended for production.
No action needed if
- All your list requests specify a
limitof at most 1000 and paginate using theoffset.
Was this page helpful?
