For my own sites, I do all of the things jonssons said, but I also use haproxy stick table to limit the number of errors a user may generate. I also route certain URI patterns to a tarpit.
At work, I show developers, ops and infrastructure folks these things and let them decide if they want to test and implement any of it.