Here's how Figma dealt with a spam attack.
An Alternative Approach to Rate Limiting. Excellent explanations of some options with great diagrams: Token bucket, Fixed window counters, Sliding window log. Their choice: fixed window counters and sliding window log inspired the algorithm that stopped the spammers. We count requests from each sender using multiple fixed time windows 1/60th the size of our rate limit’s time window...our rate limiter was accurate down to the second and significantly minimized memory usage...our attackers saw the response code change from 200 to 429 and simply created new accounts to circumvent the rate limiting on their blocked accounts. In response, we implemented a
shadow ban: On the surface, the attackers continued to receive a 200 HTTP response code, but behind the scenes we simply stopped sending document invitations after they exceeded the rate limit...