# Limits

**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](/api/limits.md). 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](/offering/support.md).

## Requests to the Experience API

### Request validation

The [router](/commerce-integration-layer/overview.md#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 | **15000** | 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 | **10000** | Matches the [maximum offset for Platform queries](/api/limits.md#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](/commerce-integration-layer/development/operations-and-performance.md#publishing-and-rollout).

| Limit | Value | Notes |
| --- | --- | --- |
| `typeDefs` size | **256 KiB** |  |
| Types, including type extensions | **200** |  |
| Fields on object, interface, and input types | **2000** | Counted across the whole schema. |
| Subscription roots | 0 | A bundle can't declare subscriptions. |
| API Extensions declared | **25** | See [Managed API Extensions](/commerce-integration-layer/limits.md#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](/commerce-integration-layer/development/operations-and-performance.md#extension-resolvers).

### 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](/commerce-integration-layer/development/configure-and-deploy.md#outbound-http-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](/commerce-integration-layer/managed-api-extensions.md) handler runs inside a Platform write, so the Platform [API Extension limits](/api/limits.md#api-extensions) apply: the default and maximum timeout, the number of expansion paths, and the dependency rules. See [Time limits](/api/projects/api-extensions.md#time-limits).

The Commerce Integration Layer adds the following:

- A handler is bound by the `timeoutInMs` on 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](/commerce-integration-layer/limits.md#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.

## Related pages

- [Area overview page with navigation](/commerce-integration-layer.md)
- [Search documentation and API specs](/search.md)