[PR #584] [CLOSED] Rough draft of reciever rate limiting for discussion #1337

Closed
opened 2026-05-07 01:01:38 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/binwiederhier/ntfy/pull/584
Author: @karmanyaahm
Created: 1/17/2023
Status: Closed

Base: user-accountHead: user-account


📝 Commits (1)

  • 84e2ee9 very very rought draft of reciever rate limiting

📊 Changes

2 files changed (+68 additions, -17 deletions)

View changed files

📝 server/server.go (+28 -9)
📝 server/topic.go (+40 -8)

📄 Description

This is the original proposal from the Matrix room
me:

My main idea, the ideal solution (as PeterCxy proposed) is to move the cost, for at least UP rate limits, to the receiver instead of the sender.

There are many ways to do it, but one potential solution (a simple but clean-ish one I could think of):

  • Like id: and user:, make up* topics a up: visitor. [1]
  • This up: visitor (the UP topic) has large-ish rate limits (to prevent obvious spam/misconfiguration), but doesn't care too much.
  • Topic.Subscribe and Topic.Unsubscribe keep track of the most recent visitor to subscribe to a topic, and the time (say prev. 12hrs is valid). [2]
  • On Topic.Publish, the message is 'billed' to the most-recent-visitor's rate limit (either ip: or user:), rejected if there is no recent visitor.
  • Delete the message if successfully delivered to at least one client. UP topics are unique to each client anyways. [3]

[1] In which case up* topics have to be reserved explicitly for receiver-based rate limiting. We cannot rely on up=1 because the client doesn't control that.
[2] If all of this is in-memory: say someone loses their connection, wait 1 hour, ntfy restarts, wait 1 hour, they resubscribe. If there was a notification at T+90 minutes, that notification would be lost, since the topic would show up as 'fresh', and the notification rejected. However, this seems like a fair compromise for the simplicity of avoiding a database.
[3] Attempt delivering to multiple clients if they are online and subscribed though, for debugging purposes. This is just an extra resource-saving measure and not part of the core plan.

I can actually help you make it now, though, once we agree on a plan, since this is needed by a clear deadline.

binwiederhier:

I think I understand this plan. In my own words:

For topics starting with up*, we keep track of the visitors that are subscribed to a topic in the topic struct.

When a message is published, we determine the visitor based on the topic name instead of the IP (v := s.visitorByTopic("upABCDEF..")). If there are multiple visitors, we pick the most recent one.

The rest of the logic remains the same.

Correct?

me:

Basically, yes. The goal is to 'bill' that messsage to the most recently subscribed visitor instead of to the sender.

Additionally, this would require formally defining 'up*' as a special namespace, since messages are "billed" differently.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/binwiederhier/ntfy/pull/584 **Author:** [@karmanyaahm](https://github.com/karmanyaahm) **Created:** 1/17/2023 **Status:** ❌ Closed **Base:** `user-account` ← **Head:** `user-account` --- ### 📝 Commits (1) - [`84e2ee9`](https://github.com/binwiederhier/ntfy/commit/84e2ee9b7c80dfb753bf54764de3c12f2e3f1dae) very very rought draft of reciever rate limiting ### 📊 Changes **2 files changed** (+68 additions, -17 deletions) <details> <summary>View changed files</summary> 📝 `server/server.go` (+28 -9) 📝 `server/topic.go` (+40 -8) </details> ### 📄 Description This is the original proposal from the Matrix room me: > My main idea, the ideal solution (as PeterCxy proposed) is to move the cost, for at least UP rate limits, to the receiver instead of the sender. > > There are many ways to do it, but one potential solution (a simple but clean-ish one I could think of): > > - Like id: and user:, make up* topics a up: visitor. [1] > - This up: visitor (the UP topic) has large-ish rate limits (to prevent obvious spam/misconfiguration), but doesn't care too much. > - Topic.Subscribe and Topic.Unsubscribe keep track of the most recent visitor to subscribe to a topic, and the time (say prev. 12hrs is valid). [2] > - On Topic.Publish, the message is 'billed' to the most-recent-visitor's rate limit (either ip: or user:), rejected if there is no recent visitor. > - Delete the message if successfully delivered to at least one client. UP topics are unique to each client anyways. [3] > > [1] In which case up* topics have to be reserved explicitly for receiver-based rate limiting. We cannot rely on up=1 because the client doesn't control that. > [2] If all of this is in-memory: say someone loses their connection, wait 1 hour, ntfy restarts, wait 1 hour, they resubscribe. If there was a notification at T+90 minutes, that notification would be lost, since the topic would show up as 'fresh', and the notification rejected. However, this seems like a fair compromise for the simplicity of avoiding a database. > [3] Attempt delivering to multiple clients if they are online and subscribed though, for debugging purposes. This is just an extra resource-saving measure and not part of the core plan. > > I can actually help you make it now, though, once we agree on a plan, since this is needed by a clear deadline. binwiederhier: > I think I understand this plan. In my own words: > > For topics starting with up*, we keep track of the visitors that are subscribed to a topic in the topic struct. > > When a message is published, we determine the visitor based on the topic name instead of the IP (v := s.visitorByTopic("upABCDEF..")). If there are multiple visitors, we pick the most recent one. > > The rest of the logic remains the same. > > Correct? me: > Basically, yes. The goal is to 'bill' that messsage to the most recently subscribed visitor instead of to the sender. > > Additionally, this would require formally defining 'up*' as a special namespace, since messages are "billed" differently. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-07 01:01:38 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ntfy#1337
No description provided.