To keep every Project fast and every extension isolated, the Commerce Integration Layer limits what a request, an extension, and a published bundle can do.
This page lists the limits the Commerce Integration Layer enforces on top of the commercetools Platform limits. Platform limits, such as the size of a JSON document or the number of update actions in a request, continue to apply to every call the Commerce Integration Layer makes to the Platform, and are not repeated here.
An operation that exceeds an enforced limit is refused. Where a limit truncates instead of refusing, the table says so.
These limits apply to every Project and can change over time. If a limit doesn't fit your use case, contact commercetools Support.
Requests to the Experience API
Request validation
The router checks these limits on every GraphQL operation before it plans the query or contacts a subgraph. The depth, token, and directive limits sit well above what storefront operations use in practice.
| Limit | Value | Notes |
|---|---|---|
| Query depth | 15 | Each fragment counts as a level. |
| Tokens per document | 15 000 | The size of the query text, not the size of the response. |
| Directive uses per operation | 50 | |
| Aliases per operation | 100 | |
| Request body | 2 MB | Larger requests are rejected with an HTTP 413 response. |
Request timeouts
The router applies these limits while it runs the operation, so an operation that passed validation can still fail partway through.
| Limit | Value | Notes |
|---|---|---|
| Total request time | 60 seconds | The whole client request, including every subgraph fetch. |
| Time per subgraph request | 35 seconds | Covers the core subgraph and your extension subgraph. |
The router has no limit on response size. It estimates the cost of each operation and records it for monitoring, but doesn't reject expensive operations.
Core subgraph queries
| Limit | Value | Notes |
|---|---|---|
Entity representations in one _entities call | 100 | Relevant when your extension resolves entities in batches. |
| Page size for Product search | 100 | |
| Page size for Orders and other Platform queries | 500 | |
| Maximum offset for Product Variants and Inventory | 10 000 | Matches the maximum offset for Platform queries. |
| Options returned per facet | 10 | Extra options are truncated. The most common options are kept. |
Schema extensions
Schema contribution
A bundle can be up to
4 MiB. This limit is checked when you push. A larger upload is rejected with an HTTP 413 response, and no revision is stored.The extension runtime checks the following limits when it loads a stored bundle, before the bundle serves any request. A bundle that exceeds a limit is refused and the failure reason is reported, so the revision follows the
failed path described in Publishing and rollout.| Limit | Value | Notes |
|---|---|---|
typeDefs size | 256 KiB | |
| Types, including type extensions | 200 | |
| Fields on object, interface, and input types | 2 000 | Counted across the whole schema. |
| Subscription roots | 0 | A bundle can't declare subscriptions. |
| API Extensions declared | 25 | See Managed API Extensions. |
After a bundle loads, the extension runtime reports the hooks it declares. A bundle can declare up to
50 hooks, each with a name of up to 100 characters. A report that exceeds these limits is rejected.Resolver execution
These limits apply to each call of a resolver, a hook, or a framework resolver such as
__resolveReference and __resolveType.| Limit | Value | Notes |
|---|---|---|
| Time per resolver or hook call | 30 seconds | The call's outbound request is aborted. |
| Outbound calls per resolver call | 10 | The call over the limit is refused. |
| Result size per field | 1 MiB of JSON | Only the data your own fields return counts. A nullable field over the limit returns null with an error. A non-nullable field over the limit fails the whole response. |
The sandbox doesn't limit CPU time or memory for a call. A synchronous loop or a very large allocation in one resolver slows every other extension that runs on the same sandbox, so keep resolver code light. For more guidance, see Operations and performance.
Outbound requests
Every outbound
fetch from a resolver, a hook, or an API Extension handler is subject to these limits, in addition to the domain allowlist.| Limit | Value | Notes |
|---|---|---|
| Time per call | 10 seconds | The call is aborted. The resolver's own time limit still bounds the total. |
| Request body | 4 MiB | Measured for bodies of known size that you pass in the request's init. |
| Response body | 10 MiB | A response that is too large is refused. |
| Redirects | Not followed | A redirect can't lead a call outside the allowlist. Call the final URL directly. |
Managed API Extensions
A Managed API Extension handler runs inside a Platform write, so the Platform API Extension limits apply: the default and maximum timeout, the number of expansion paths, and the dependency rules. See Time limits.
The Commerce Integration Layer adds the following:
- A handler is bound by the
timeoutInMson its declaration, or by your Project's Platform timeout limit when you omit it. - A handler's callback payload is limited to about
6 MiB, which is about the size the Platform itself allows. - A handler isn't subject to the limit on outbound calls per resolver call. Its outbound calls are still held to the per-call time limit and the body-size limits in Outbound requests.
Configuration
| Limit | Value | Notes |
|---|---|---|
| Extension configuration request | 256 KiB | The whole list of configuration entries in one request. |
| Project settings request | 256 KiB | Covers Project settings, checkout settings, schema visibility, and identity provider settings. |
Limit breach logs
When an extension exceeds one of the sandbox limits above, the extension runtime writes a warning to the extension's logs. Filter on the
event field instead of the message text.| Field | Value |
|---|---|
| Message | EXTENSION LIMIT EXCEEDED |
event | extension.limit_exceeded |
extension.limit.name | The stable identifier of the limit |
extension.limit.max | The limit |
extension.limit.observed | The value that exceeded it |
extension.limit.unit | bytes or count |
extension.limit.mode | enforce when the operation was refused |
You can alert on this message in your own monitoring tool.