Putting a timeout seems to be helping a lot because it's a sweeping fix. That combined with rate-limiting ws messages covers the basics. But I think I need to also punish slow queries similar to rate-limiting, so that if you spend too much query time over a period you get blocked for a short period.
In chorus, every connection is IP blocked for 1 second after disconnection. That is to prevent rapid reconneciton loops. That block last longer on bad behavior.