# Limits and quotas

> jsonpad meters two things: how many requests you make in a calendar month, and how many bytes you have stored. Everything else on your plan is a guard rail against a runaway loop rather than something you should need to design around.

Source: https://jsonpad.io/docs/limits-and-quotas

---

jsonpad meters two things: how many requests you make in a calendar month, and how many bytes you have stored. Everything else on your plan is a guard rail against a runaway loop rather than something you should need to design around.

If you are writing a client or an agent that talks to jsonpad unattended, this is the page to read: the response headers below are what let it pace itself, and the degradation behaviour is what lets it keep working when it runs out. To check your limits and usage in a single request, call [`GET /tokens/self`](https://jsonpad.io/docs/token-view-self.md).

<a id="what-counts"></a>

## What counts as a request

Every API call authenticated with an API token counts as one request against your monthly allowance, regardless of method or response status.

Four things do not count:

-   Requests made by the jsonpad dashboard while you are signed in. Browsing your own data through the website is free.
-   Requests that fail with a `5xx` status. If we break, you get the request back.
-   Requests made after your allowance and credits have run out, whether they are refused or served at the reduced rate. A request pack you buy later only pays for requests made after you buy it.
-   Requests refused by a [rate limit](https://jsonpad.io/docs/limits-and-quotas.md#rate-limits). Backing off and retrying costs you nothing.

Realtime websocket messages are not metered either. Instead, each plan caps how many concurrent realtime connections a single account may hold open; a connection beyond that cap is refused at connection time, and is told how long to wait before trying again. See [connection limits](https://jsonpad.io/docs/realtime-updates.md#connection-limits).

Outbound [webhook](https://jsonpad.io/docs/webhooks.md) deliveries are not metered either. Each plan caps how many webhooks an account can have (1 on Free, 5 on Indie, 20 on Pro and 50 on Scale).

A [flow](https://jsonpad.io/docs/flows.md) costs what the same API calls would: calling an endpoint flow, or an event flow running, is one request, and each item the flow reads or writes is one more. Runs you start in the dashboard, and test runs, are free. Each plan caps how many flows an account can have (2 on Free, 10 on Indie, 50 on Pro and 250 on Scale).

<a id="response-headers"></a>

## Response headers

Every metered response carries the headers below, alongside the per-minute headers described under [rate limits](https://jsonpad.io/docs/limits-and-quotas.md#rate-limits). All of them can be read from JavaScript running in a browser as well as from a server.

-   `x-quota-total`: The request allowance for the current month, excluding any overdraft and any prepaid credits. Example: `25000`
-   `x-quota-remaining`: How many requests are left before writes start being refused. This includes your plan's overdraft and any prepaid credits you hold, so it can be larger than `x-quota-total`. Example: `18342`
-   `x-quota-credits`: How many prepaid requests you currently hold. These never expire and are only drawn down once the monthly allowance and overdraft are gone. Example: `0`
-   `x-quota-reset`: An ISO 8601 timestamp for when the allowance next resets. Example: `2026-10-01T00:00:00.000Z`
-   `x-quota-degraded`: Only present on a read served at the free tier's rate limit because your allowance and credits have run out. See below. Example: `true`

<a id="running-out"></a>

## What happens when you run out

We email you once, when you cross 80% of your allowance. There is no second email at 90%.

At 100%, in order:

1.  On a paid plan you enter a 10% overdraft, and nothing changes. The free plan has no overdraft.
2.  Past the overdraft, any prepaid request credits you hold are drawn down. Again, nothing changes until they run out.
3.  Once those are gone, `GET`, `HEAD` and `OPTIONS` requests keep working, but at the free tier's rate limit. Every other method returns
    
    429 Too Many Requests
    
    with the error code `QUOTA_EXCEEDED` and a `retry-after` header.

In other words, your application degrades to read-only rather than going dark. Whatever you have already stored stays readable.

```json
{
  "name": "QUOTA_EXCEEDED",
  "code": 10013,
  "message": "Monthly request quota exceeded. Your allowance resets at 2026-10-01T00:00:00.000Z. Read requests still work; to resume writing now, upgrade your plan or buy a request pack at https://jsonpad.io/pricing"
}
```

Buying a [prepaid request pack](https://jsonpad.io/pricing#request-packs) takes effect immediately and does not change your plan.

<a id="reset"></a>

## When the allowance resets

At 00:00 UTC on the first of each calendar month, not on your billing anniversary. Free accounts have no anniversary, and a fixed reset date means an upgrade never has to prorate your allowance.

Prepaid credits carry over. Unused monthly allowance does not.

<a id="storage"></a>

## Storage

Each plan has a total storage allowance covering the JSON data of every item in every one of your lists. Stored bytes are recalculated once a day rather than on every write, so the figure you see on your dashboard can be up to a day behind.

If you are over the allowance, reads keep working and writes return

403 Forbidden

with the error code `STORAGE_LIMIT_EXCEEDED` until you delete some data or move up a plan. Nothing is ever deleted for you.

<a id="rate-limits"></a>

## Rate limits

Separately from the monthly allowance, each plan limits how fast you can make requests: a maximum number of requests per minute, and a minimum gap between consecutive requests. Exceeding either returns

429 Too Many Requests

with the error code `RATE_LIMIT_EXCEEDED` and a `retry-after` header telling you how many seconds to wait. A refused request does not count against your monthly allowance.

Every response to a request made with an API token, including a refused one, carries two headers describing the per-minute limit:

-   `x-rate-limit-total`: How many requests your plan allows per minute. Example: `60`
-   `x-rate-limit-remaining`: How many more requests you can make after this one before reaching that limit. The minute is a rolling window over the last 60 seconds. Example: `42`

Rate limits exist to stop one account degrading the service for everyone. They are not something you should have to plan around: if you are hitting them during normal operation, add a short delay between requests rather than retrying immediately.

<a id="version-history"></a>

## Version history

Each plan retains a number of versions per item. Older versions remain in the [event log](https://jsonpad.io/docs/event-log.md) — we never delete event history — but they can no longer be fetched back through the `version` query parameter, and requesting one returns

410 Gone

with the error code `ITEM_VERSION_NOT_RETAINED`.

<a id="write-rules"></a>

## Write rules

[Write rules](https://jsonpad.io/docs/write-rules.md) have to finish, quickly, on every write, so the language has no loops and no recursion and evaluation has a budget. These limits are the same on every plan, including free:

-   `rule text` (64 KiB): Checked when the rules are saved.
-   `statements` (200): `allow` and `require` statements in one rule set.
-   `expressions` (5,000): Across the whole rule set, counting each call to one of your own functions as the size of its body.
-   `nesting depth` (64): Brackets and unary operators, with a separate cap of 500 on the height of an expression — every operator in a chain like `a && b && c` is one level.
-   `function parameters` (8): Per declared function.
-   `evaluation budget` (100,000 units): Per write. Roughly one unit per expression evaluated, and more for work over large values: comparing, diffing, hashing and string handling all cost by size. Running out refuses the write with `WRITE_RULE_DENIED`. Ordinary rules use a tiny fraction of it, and the dashboard's playground shows you how much.
-   `lookups` (10 items): Different items one write's rules can read with `lookup()` and `exists()`. Reading the same item again doesn't count twice. A lookup past the limit is an error, so the statement making it isn't true. Each item read counts as a request.
-   `value depth` (256): How deeply nested a value can be when it's compared, diffed or hashed.
-   `rule tests` (200 / 256 KiB): Stored per list, as a count and as a size.

Refused writes are counted in your list's stats, and the last 50 per list are kept so you can see what was refused and why.

<a id="uncapped"></a>

## What is not limited

Lists, items per list and indexes per list are uncapped on every plan, including free. In practice what you can store is bounded by the storage allowance rather than by a count.

Every feature is available on every plan too: JSON schema validation, version history, JSON Patch, JSON Pointer, JSON Path, realtime updates and identities. You never need to move up a plan to unlock a capability — only to get more volume.

The current numbers for each plan are on the [pricing page](https://jsonpad.io/pricing).
