Rate limiter module for Remotes

Not sure why but, could you explain why this would cause a memory leak?

1 Like

Because the connection is not disconnected, it will be called more times than it should. If you keep firing the function the event is going to be ran another time.

I can’t really explain this too well, this thread is a good read.

2 Likes

I thought roblox already monitors this. If a client over calls the remote then that player will get throttled not the others?

1 Like

afaik it shouldn’t impact other clients, it doesn’t make sense to compromise other users when they aren’t involved.

Although Roblox does monitor this it’s for a different purpose and does a different thing, which that’s not the point of having this in your game, it’s to filter out Exploiters from Legitimate Clients.

1 Like

Roblox has no way to know if a remote is being ‘over-throttled’ or not; some remotes are supposed to be fired a lot, some are not.

The point of throttling the remotes yourself is to reduce the stress on the server that may be caused when clients trigger a resource-heavy task multiple times (and too frequently!).

The point @RuizuKun_Dev made is also valid. When, for instance, an exploiter fires a remote too many times, it should not negatively impact the experience for the other players (by having the server crash or by disabling the function attached to the remote completely). This was the main motivation behind making and publishing this module.

1 Like

This post has often been quoted in the context of other networking problems.
I recently wrote this reply for someone that goes more in-depth on ping, lag, and on how you could tackle some of the other networking problems related to guns in an FPS game:

Unless I misunderstand, isn’t this kind of completely pointless? Anybody can limit players from proceeding in the event with an if statement (and not having to wrap in a pointless function abstraction that uncessarily uses self :wink: )

To actually rate limit, i.e block the server from responding to a certain players request at all, is far different. Because as it stands if that player is exploiting and firing the remote hundreds of times a second, this will do nothing besides stop the server code from executing, in fact because of your module implementation you may end up causing server lag.

Yes, you indeed seem to misunderstand.

Indeed, this module limits the code on the server from executing if a rate is exceeded, therefore reducing stress on the server. This practice is very common and I recommend that you look more into the subject.

This claim is not true at all, all my module does is relatively inexpensive, e.g. manipulating a table. (As you can see in the source code.)

therefore reducing stress on the server.

This doesn’t reduce stress on the server, sure, it’ll stop the code you want to execute from executing, but you don’t seem to know what I mean. What I mean is, if they fire that remote hundreds of times, that event will still fire hundreds of times, that if statement will still conditionally check hundreds of times. Nothing has changed besides the extent to which the player proceeds to. And it’s already too far.

This claim is not true at all, all my module does is relatively inexpensive, e.g. manipulating a table. (As you can see in the source code.)

I’m pretty sure I said the wrong thing on this part, while you may not cause server lag per se, wrapping this in a, again uneeded function call that also doesn’t use self but has it there anyway. It will be more expensive than literally just having only an if statement.

So instead of making wrappers for something that doesn’t actually save any resources, (if anything, the opposite effect compared to standard implementation of this) I’d suggest you instead make a tutorial advising people on this practice of stopping remote abuse.

2 Likes

Can you make RemoteFunction version of this module, please? Nice module, though!

The module works for both RemoteEvents and RemoteFunctions!
In the source code, there are detailed instructions on how to use my module + code examples.

1 Like

I think you’re confused about the expense of function calls - i.e. the lack thereof of any actual cost.

What you’re suggesting is sanity checks (I think?) - those should be included on top of a module like this. Using catch all solutions, like a rate limiting wrapper, is good practice because it acts as a safeguard against accidental failure to implement proper controls (the risk of accidentally allowing a DoS-style attack is increased by relying on sanity checks on every single remote, rather than wrapping them in a module which sorts it for you).

The cost to something like this is minimal, if not plain negligible, and the benefit is pretty clear from a security and performance perspective.

4 Likes

It wasn’t clear from here if I could check if the player is being throttled from a LocalScript (to for instance notify them of this) without it limiting the amount of uses a player gets.

To be more precise, I’m thinking of adding a sort of “Panic Button” function to a custom chat script, and using this to not only prevent spamming remote events but also implement the delay of 20 seconds, or (0.1 allowed times per second)

Is it a good idea for example:
You make a cooldown on the client that lasts 1 second, then on the server you make it so if its fired more than 5 times a second you kick the player, is that a good idea?

The client firing more often than should be possible indeed seems like a sign of a client exploiting. Make sure to test your system enough to avoid false positives caused by a player’s slow or unstable internet connection. I’m unsure if Roblox queues up remote requests (and fires them rapidly when the connection is back) or ignores them in these cases.

In any case, it’s good practice to make sure nothing happens when the event is indeed exceeding its expected limits.

(Sorry for the late reply.)

This is a very late response and I like Xander’s response above, but no you probably shouldn’t just be kicking players that fire a remote like that.

Let me put it into a reasonable ideal:

  • Using this module, you can limit all players requests very simply.

  • If you do it right, there’s no difference from an exploiter and someone with a really good macro or someone on a constant grind.

So rather than finding edge-case solutions for punishing the exploiters (who you cannot truly differentiate,) you should instead focus on making their exploits less harmful to the balance of your game.

1 Like

sorry for the slight bump but i cant seem to get this working on my gun, it only works once for me

for context the gun is completely client sided and the bullets and audio are handled on the server

this is the server code:

FireGun.OnServerEvent:Connect(function(plr)
	local gun = plr.Character:FindFirstChildWhichIsA('Tool')
	if gun:FindFirstChild('GunModule') then
		if gun and FloodCheck:Check(plr, FireGun, require(gun.GunModule).commons.Rate) then
			if GunFires:FindFirstChild(gun.Name) then
				local sfx = GunFires:FindFirstChild(gun.Name)
				local firesound = sfx.Fire:Clone()
				firesound.Parent = gun.Handle
				firesound:Play()
				firesound.Ended:Connect(function()
					firesound:Destroy()
				end)
			else
				plr:Kick('Error: Could not locate cooresponding gun sound')
			end
		end
	else
		plr:Kick('Error: No gun module')
	end
end)

if you need more info let me know

no, make the ratelimit both in client and server, and if server detecyed it reached that limit irs very obvious its an exploiter and you should kick it.

You should probably add some leeway in the rate of the flood check and not make it equal to the exact firing rate. This accounts for a variable networking delay etc.

I’d also recommend handling the sounds and effects on the client and not on the server. This will decrease latency and will make your guns feel more responsive.

With your supplied code, I’m unable to tell what’s preventing your gun from shooting a second time. Perhaps it’s the code running on the client? Perhaps Scripting support could help you out further? If after debugging, you believe it’s my module that’s the cause of the problem, then feel free to DM me and maybe we can help each other to fix it. (DMing for other help is fine too, but the scripting support forum is likely quicker.)

i’ve already fixed this issue, i just used a table with the players user id, though ill provide some answers if i want to use this in the future

i have tested it in game with a friend and it seems like there isn’t noticeable a delay to the sound or bullets

yeah, i was just doing that temporarily since i just wanted to get the main system done first

i don’t think so, all the script did was fire a remote event with no parameters