# System Limits

Meridian applies rate limits and account limits to protect the exchange. Configuration can differ by environment and account tier.

## Get Current Rate Limits

Query the environment before you start a high-rate integration:

```http
GET /v1/rate-limit/config
```

The response lists each rate-limited HTTP and WebSocket route. A fixed-cost route has `fixedPoints`. A paginated route has `basePoints` and `pointsPerRow`. Do not hard-code these values.

## Rate-Limit Pools

Meridian uses three point pools:

| Pool      | Identifier      | Applies to                                      |
| --------- | --------------- | ----------------------------------------------- |
| HTTP      | IP address      | Each HTTP request                               |
| WebSocket | IP address      | Connections and subscription actions            |
| Account   | Account address | Authenticated requests from all its subaccounts |

An authenticated request consumes from the HTTP pool and the account pool. Meridian rejects the request if either pool has no remaining points. A public request does not consume account points.

Account quotas can vary by tier. The configured tiers include user, builder, maker, super maker, and system accounts.

## How Points Are Charged

The pools are independent, so one request can consume from more than one pool.

* A fixed-cost route consumes its configured `fixedPoints`.
* A paginated route consumes `basePoints + ceil(rows returned × pointsPerRow)`.
* An authenticated action can also consume from the account pool. Its account cost can differ from its HTTP route cost.

The account pool is keyed by the owner account, so activity from all of its subaccounts and linked signers shares the same account quota. IP points are shared by clients using the same public IP address.

Points are not automatically refunded when an operation fails after admission. Use the response headers as the source of truth instead of estimating the remaining balance locally.

## Response Headers

Rate-limited HTTP endpoints return these headers:

```text
RateLimit-Limit: <points in the window>
RateLimit-Remaining: <points that remain>
RateLimit-Reset: <seconds until reset>
Retry-After: <seconds until retry>
```

`Retry-After` is present when the API rejects a request because of a rate limit. Wait for that interval before you retry. Add random jitter when many workers share one quota.

On a `429`, use the error body's `type` field to identify which pool rejected the request.

The error body identifies the affected limit. Values can include:

* `RATE_LIMIT_IP`
* `RATE_LIMIT_ACCOUNT`
* `RATE_LIMIT_WITHDRAW`
* `RATE_LIMIT_CONVERSION`
* `RATE_LIMIT_LINKED_SIGNER`

## WebSocket Limits

A WebSocket connection has a maximum lifetime of approximately 4 hours. The server also closes an idle or overloaded connection. A client must reconnect, restore its subscriptions, and rebuild any local order-book state from a new snapshot.

The current default allows 50 subaccount stream subscriptions on one connection. Each `(subaccountId, streamType)` pair counts as one subscription. Product-level market streams do not use this subaccount limit.

If the client exceeds the limit, the server returns:

```json
{ "ok": false, "code": "SUBSCRIPTION_LIMIT_EXCEEDED" }
```

The server sends WebSocket ping frames automatically. A client must respond according to its WebSocket library's requirements.

## Account Safeguards

The exchange has these configured safeguards in addition to point-based rate limits:

* A subaccount can have at most 50 open positions.
* A subaccount can have at most 250 working orders across all markets.
* A subaccount can have at most 50 working orders in any one market.
* A subaccount can initiate at most 10 withdrawals in a rolling 1-day period.
* A subaccount can initiate at most 10 token conversions in a rolling 1-day period.
* A targeted cancel request can identify at most 200 orders across `orderIds` and `clientOrderIds`. The subaccount-scoped cancel-all endpoint does not send order IDs.

The withdrawal and conversion limits count transfer records created during the window, including records that later fail to settle. A conversion rejected at the admission stage is not recorded and does not count. When the conversion limit is reached, the API returns `429` with `RATE_LIMIT_CONVERSION`.

These safeguards are configurable and can differ by environment. Query the linked-signer quota with:

```http
GET /v1/linked-signer/quota?subaccountId=SUBACCOUNT_UUID
```

If the active linked-signer limit is reached, the API returns a forbidden response. Revoke an unneeded signer before you add another signer.

## Maintenance Mode

Check the current API maintenance state:

```http
GET /v1/maintenance
```

The response contains `isEnabled`. When this value is `true`, the API rejects order submissions, cancellations, token conversions, withdrawals, and linked-signer changes with a service-unavailable response. Public read endpoints remain available unless a separate service problem affects them.

## Retry Rules

* Retry `429` responses after the `Retry-After` interval.
* Do not retry a validation or signature error without changing the request.
* Use an idempotent client order ID when you retry an order after a network timeout.
* Do not reuse an EIP-712 nonce for a new action.

See the [interactive API reference](/protocol-reference/api-hosts) for the current endpoint schemas.
