Author

Topic: Suggestion: Use the token bucket algorithm for rate-limiting posts and searches (Read 985 times)

newbie
Activity: 19
Merit: 0
Currently, newbies have to wait 360s between two posts (including PMs) and 90s between two searches (including switching the search result page!).
This is quite annoying when you want to respond to multiple threads / PMs at once (for example after logging in and catching up on your threads/PMs)
The search delay might even be counterproductive because it discourages newbies from searching.
I understand that some kind of rate limiting for newbies is needed in order to reduce spam attacks.
For this reason, I propose using the "token bucket" (https://en.wikipedia.org/wiki/Token_bucket) algorithm for rate-limiting newbies' posts and searches instead of a fixed delay.

Example:
Every user or IP gets an own "post bucket" that can hold 10 tokens.
Every [postDelay] seconds, a token is added to every non-full bucket.
When a user wants to post, a token is taken from his bucket. If the bucket is empty, he gets a "You're posting too often, wait n seconds" error.

This way, the annoying delay shouldn't occur anymore for most newbies but if they want to spam, they still get rate-limited.
The exact bucket size can be adjusted of course, 10 tokens is just some example number.
For searching, a seperate bucket can be used in order to implement different post/search delays.

Note that in the implementation, you don't actually have to call some "add tokens" script every N seconds.
In fact, there would be hardly any performance penalty if you do it like this:

Code:
pseudocodeFunction userWantsToPost(userid):
currentTime = getCurrentTime()

# get user-specific information from DB.
lastTokenTime = getLastTokenTime(userid)
numberOfTokens = getUserTokens(userid)
postDelay = getUserPostDelay(userid)

# calculate current number of tokens
numberOfTokens += (currentTime - lastTokenTime) / postDelay
lastTokenTime += numberOfTokens * postDelay

# try to take a token. if there are no tokens, deny the post request
if(numberOfTokens > 0)
--numberOfTokens
allowPost()
else
rejectPost("You're posting too often!")

# store number of tokens and last token time in DB
setLastTokenTime(lastTokenTime)
setUserTokens(numberOfTokens)
Jump to: