From cf108ff713309abd6f01e9d2caa7f82c4d13e295 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 2 Jul 2026 16:12:22 -0400 Subject: [PATCH 1/3] Fix the pagination issue. --- 01.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/01.md b/01.md index 6f26a3a8f7..6c8cf29c61 100644 --- a/01.md +++ b/01.md @@ -146,7 +146,15 @@ All conditions of a filter that are specified must match for an event for it to A `REQ` message may contain multiple filters. In this case, events that match any of the filters are to be returned, i.e., multiple filters are to be interpreted as `||` conditions. -The `limit` property of a filter is only valid for the initial query and MUST be ignored afterwards. When `limit: n` is present it is assumed that the events returned in the initial query will be the last `n` events ordered by the `created_at`. Newer events should appear first, and in the case of ties the event with the lowest id (first in lexical order) should be first. Relays SHOULD use the `limit` value to guide how many events are returned in the initial response. Returning fewer events is acceptable, but returning (much) more should be avoided to prevent overwhelming clients. +The `limit` property of a filter is only valid for the initial query and MUST be ignored afterwards. When `limit: n` is present it is assumed that the events returned in the initial query will be the last `n` events ordered by the `created_at`. Newer events should appear first, and in the case of ties the event with the lowest id (first in lexical order) should be first. Relays SHOULD use the `limit` value to guide how many events are returned in the initial response. Returning fewer events is acceptable, but returning (much) more should be avoided to prevent overwhelming clients. + +### Pagination & limits + +Relays that impose a maximum `limit` MUST set it greater than the largest number of events sharing a single `created_at` in their database, so no single second can fill a page and stall pagination. A relay that violates this forces clients to either stall or skip and drop events; there is no client-side fix. + +To page backwards safely, clients MUST repeat requests with `until = oldest` (inclusive) and MUST deduplicate by `id`, since the oldest second is re-fetched each round. Paging is complete when a round yields no new events after deduplication. During this process, clients MUST detect a full page whose oldest and newest events share one `created_at`; if so, the client MUST retry that second with a larger `limit`. If the relay clamps the larger `limit` and still returns a page confined to one `created_at`, the client MUST either advance with `until = oldest - 1`, treating the unretrieved events as dropped, or abort. + +For normal paging, clients MUST NOT set `limit`; they MUST accept the relay maximum, since a value below a relay's densest second reintroduces the stall. Raising `limit` to drain a stuck second, as above, is the only exception. ### From relay to client: sending events and notices From cdadcbf9fe3cbe9ff130e92c608e9b4589a5608f Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 2 Jul 2026 16:14:50 -0400 Subject: [PATCH 2/3] Trying to fix diffs --- 01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01.md b/01.md index 6c8cf29c61..6845da396b 100644 --- a/01.md +++ b/01.md @@ -146,7 +146,7 @@ All conditions of a filter that are specified must match for an event for it to A `REQ` message may contain multiple filters. In this case, events that match any of the filters are to be returned, i.e., multiple filters are to be interpreted as `||` conditions. -The `limit` property of a filter is only valid for the initial query and MUST be ignored afterwards. When `limit: n` is present it is assumed that the events returned in the initial query will be the last `n` events ordered by the `created_at`. Newer events should appear first, and in the case of ties the event with the lowest id (first in lexical order) should be first. Relays SHOULD use the `limit` value to guide how many events are returned in the initial response. Returning fewer events is acceptable, but returning (much) more should be avoided to prevent overwhelming clients. +The `limit` property of a filter is only valid for the initial query and MUST be ignored afterwards. When `limit: n` is present it is assumed that the events returned in the initial query will be the last `n` events ordered by the `created_at`. Newer events should appear first, and in the case of ties the event with the lowest id (first in lexical order) should be first. Relays SHOULD use the `limit` value to guide how many events are returned in the initial response. Returning fewer events is acceptable, but returning (much) more should be avoided to prevent overwhelming clients. ### Pagination & limits From 472f0b0ac9f389b6923570ef8cc4fb73b3b9daae Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 9 Jul 2026 17:38:53 -0400 Subject: [PATCH 3/3] Update 01.md Sharper language --- 01.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/01.md b/01.md index 6845da396b..1915a7d704 100644 --- a/01.md +++ b/01.md @@ -150,11 +150,9 @@ The `limit` property of a filter is only valid for the initial query and MUST be ### Pagination & limits -Relays that impose a maximum `limit` MUST set it greater than the largest number of events sharing a single `created_at` in their database, so no single second can fill a page and stall pagination. A relay that violates this forces clients to either stall or skip and drop events; there is no client-side fix. +Relays that impose a maximum `limit` MUST set it greater than the largest number of events sharing a single `created_at`, so no second can fill a page and stall pagination. A relay that violates this leaves clients no fix but to stall or drop events. -To page backwards safely, clients MUST repeat requests with `until = oldest` (inclusive) and MUST deduplicate by `id`, since the oldest second is re-fetched each round. Paging is complete when a round yields no new events after deduplication. During this process, clients MUST detect a full page whose oldest and newest events share one `created_at`; if so, the client MUST retry that second with a larger `limit`. If the relay clamps the larger `limit` and still returns a page confined to one `created_at`, the client MUST either advance with `until = oldest - 1`, treating the unretrieved events as dropped, or abort. - -For normal paging, clients MUST NOT set `limit`; they MUST accept the relay maximum, since a value below a relay's densest second reintroduces the stall. Raising `limit` to drain a stuck second, as above, is the only exception. +To page backwards, clients MUST repeat requests with `until = oldest` (inclusive), deduplicating by `id` since the oldest second is re-fetched each round; paging is complete when a round yields no new events. Clients MUST detect a full page whose oldest and newest events share one `created_at`, and MUST then either advance with `until = oldest - 1`, dropping the unretrieved events, or abort. For paging, clients MUST NOT set `limit`; they MUST accept the relay maximum, since a smaller value reintroduces the stall. ### From relay to client: sending events and notices