{"id":"a26863e802e1cd356a841216336e48ba13d3159afcedfcc23b0618d442c0564e","pubkey":"7cc328a08ddb2afdf9f9be77beff4c83489ff979721827d628a542f32a247c0e","created_at":1783892105,"kind":30817,"tags":[["title","Relay Connection Limits"],["client","better-nips"],["d","relay-connection-limits"]],"content":"NIP-65535\n======\n\nRelay Connection State (`LIMITS`)\n----------------------\n\nOriginal PR source: https://github.com/vitorpamplona/nips/blob/4b9718ff34f47ebc4445752bb7990b055b90bb18/22.md\n\n`draft` `optional`\n\nRelays can tell a Client, at any moment, what the Client is currently allowed to do on this connection — instead of the Client discovering it one rejection at a time.\n\n```json\n[\"LIMITS\", { <limit_properties> }]\n```\n\n## When it is sent\n\nThe relay SHOULD send a `LIMITS` message upon connection, and again any time the Client's rights change (payment received, session state change, etc.).\n\nThe relay MUST send a `LIMITS` message after responding `OK true` to a [NIP-42](42.md) `AUTH` event, even if nothing changed. This gives Clients a deterministic re-evaluation point:\n\n```\nconnect → await LIMITS → (AUTH → await LIMITS)? → act\n```\n\nEach `LIMITS` message is a complete statement of the connection's current state and replaces any previous one. A property absent from the payload means the relay declares no constraint for it.\n\n## Access properties (authoritative)\n\n- `can_read: <true|false>`, If false, Clients MUST NOT send `REQ` messages.\n- `can_write: <true|false>`, If false, Clients MUST NOT publish events.\n- `auth_for_read: <true|false>`, If true, authenticating via [NIP-42](42.md) may change `can_read` and/or the read limits below.\n- `auth_for_write: <true|false>`, If true, authenticating via [NIP-42](42.md) may change `can_write` and/or the write limits below.\n\nClient guidance: if `can_read` or `can_write` is false and the corresponding `auth_for_*` is not true, the Client SHOULD remove the relay from its read or publish pool for the rest of the session rather than retrying. If `auth_for_*` is true, the Client MAY authenticate proactively and wait for the follow-up `LIMITS` before proceeding.\n\n## Transport properties (advisory)\n\nThe relay enforces its limits regardless; these exist so Clients can pre-filter and shape their request loops instead of learning limits through rejections. Clients SHOULD respect them to avoid wasted round-trips.\n\n- `max_message_length: <int>`, Maximum length of any websocket message. Clients SHOULD crop/chunk `REQ` filters and withhold oversized events accordingly.\n- `max_subscriptions: <int>`, Maximum concurrent subscriptions. Clients SHOULD pool or multiplex their subscriptions to fit.\n- `max_filters: <int>`, Maximum filters per `REQ`. Clients SHOULD chunk larger requests.\n- `max_limit: <int>`, Maximum `limit` honored per filter. Clients SHOULD clamp `limit` to this value and paginate with `since`/`until` for additional results.\n- `max_event_tags: <int>`, Maximum `.tags` length of a published event.\n- `max_content_length: <int>`, Maximum `.content` length of a published event.\n\n## What this NIP intentionally does not cover\n\nThis NIP does not attempt to encode relay policy (accepted event kinds, proof-of-work requirements, rate limits, required tags, etc.). Event acceptance policies vary too widely across relay implementations to be collapsed into a single `LIMITS` payload; relays SHOULD continue to communicate policy decisions per-event via `OK` and `CLOSED` messages.\n\n## Relationship to NIP-11\n\n[NIP-11](11.md)'s `limitation` object is a static, best-effort document describing the relay in general. `LIMITS` is live and per-connection: it reflects what *this* Client, in *its* current authentication and session state, can do right now — something a static document cannot express. Where the two disagree, `LIMITS` wins for the duration of the connection.","sig":"3a8f9258571c48f76c4dfddcbeeb2b3069bc7c70e29f23b698637b178e6ced29ecd4d30f9b0d91f3813ca4ed96c75a4f0210f878f9e4f5d5cbbc18701792f96b"}