iptables can limit the number of connections per ip in a "cheap" (fast/early) way. In fact is my #1 use of iptables since blocking ports where there are no services doesn't do much.
Best practice is 'defense in depth', not 'we'll just lock down the perimeter'.
I also like nginx's limit_zone module. You can put limit_zone in the proxy stanza, and only throttle dynamic requests without throttling access to fast static files.
We often use Rack::Attack to throttle particular HTTP paths differently. Say, the homepage isn't throttled, but the login action is. That layer 7 knowledge is Rack::Attack's main advantage.
As I say in the README, Rack::Attack is complementary to iptables and the limit_zone module.
| blocking ports where there are no services doesn't
| do much
True, but it can be a useful 'just in-case' against things listening on ports that you were unaware of. It's obviously bad for you not to know about services that are listening on your box, but you could view it as a safety net.