Skip to main content
npayload is launching soon.
npayloadDocs
Platform

Limits and quotas

Rate limits, payload limits, and per-tier quotas

npayload enforces limits to ensure platform stability and fair usage. Limits vary by billing tier.

API rate limits

Requests per second, per API key:

OperationFreeProEnterprise
Publish1001,000Unlimited
Subscribe50500Unlimited
Query2002,000Unlimited

Rate limits are applied per API key, not per organisation. If you have multiple API keys, each has its own limit.

Payload limits

LimitValue
Max message size256 KB
Max batch size100 messages
Max batch payload10 MB
Max channel name length256 characters

Resource limits

ResourceFreeProEnterprise
Channels per app1,00010,000Unlimited
Subscriptions per channel1001,000Unlimited
Consumer group size10100Unlimited
Apps per organisation320Unlimited
API keys per app550Unlimited
Webhook endpoints per subscription111
DLQ entries per channel10,000100,000Unlimited
Event catalogue schemas per app50500Unlimited

Rate limit response headers

Every API response includes rate limit headers:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed per window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait before retrying (only on 429 responses)

Handling 429 responses

When you exceed a rate limit, the API returns 429 Too Many Requests. Use exponential backoff with the Retry-After header:

import { NPayload, RateLimitError } from '@npayload/node';

const npayload = new NPayload({
  clientId: process.env.NPAYLOAD_CLIENT_ID,
  clientSecret: process.env.NPAYLOAD_CLIENT_SECRET,
});

async function publishWithBackoff(channel: string, payload: unknown) {
  const maxRetries = 5;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await npayload.messages.publish({ channel, payload });
    } catch (error) {
      if (error instanceof RateLimitError && attempt < maxRetries - 1) {
        const delay = error.retryAfter
          ? error.retryAfter * 1000
          : Math.pow(2, attempt) * 1000;
        await new Promise((resolve) => setTimeout(resolve, delay));
        continue;
      }
      throw error;
    }
  }
}

Do not retry immediately after a 429 response. Always wait for at least the duration specified in the Retry-After header. Repeated rapid retries may result in extended throttling.

Requesting limit increases

If your use case requires higher limits:

  1. Pro tier: Upgrade from Free to Pro for 10x higher limits across all resources
  2. Enterprise tier: Contact sales for custom limits tailored to your workload
  3. Temporary increases: For planned traffic spikes (product launches, migrations), contact support at least 48 hours in advance

Enterprise customers can request custom limits for any resource. Contact sales@npayload.com to discuss your requirements.

Next steps

  • Rate limits for per-endpoint rate limits and best practices
  • Error codes for handling rate limit and quota error responses
  • Security for authentication and access control

Was this page helpful?

On this page