Skip to content

Rate limiting messages

PartyKit is very fast, and can process hundreds of messages per second from a single WebSocket connection, and thousands per second per room.

However, this is not always a desired behavior! For example, a connected client may misbehave (accidentally or on purpose), and spam the room with messages on a loop. If you’re a security expert, you may be thinking of spambots. If you’re a React developer, you may be thinking of a runaway useEffect with a missing memo variable.

You can prevent scenarios like these by applying rate limiting to your connections.

Rate limiting messages from a connection

In order to keep track of how frequently a specific connection sends messages, you can use the connection.state variable to track most recent messages:

onMessage(message: string, sender: Party.Connection<{ lastMessageTime?: number }>) {
const now = Date.now();
const prev = sender.state?.lastMessageTime;
if (prev && now < (prev + 1000)) {
// if previous message was less than 1 second ago, remove them from the room!
sender.close();
} else {
// otherwise keep track of the previous time
sender.setState({ lastMessageTime: now });
}
}

The above example is rather unfriendly. You are welcome to implement a rate-limiting approach that makes sense for you.

Our live reaction counter example contains a simple, incremental back-off rate limiter, which sends the client warnings before terminating the connection.

You can use it as follows:

onMessage(message: string, sender: Party.Connection) {
// rate limit incoming messages to every 100ms with an incremental back-off
rateLimit(sender, 100, () => {
// do things
});
}

Fine-grained rate limiting

To implement more sophisticated rate-limiting algorithms, you can implement your own, or reach for an open source library like the rate-limiter-flexible package on npm.