# Rate Limiting A handful of endpoints — login, checkout, order creation — are both expensive and abuse-prone. The platform defends them at **two levels**: a broad HTTP throttle, and a precise application-level limiter. ## Level 1 — HTTP throttling with Rack::Attack `Rack::Attack` sits in the middleware stack and throttles requests before they ever reach a controller. It is configured entirely through environment variables, so limits can be tuned per environment without a deploy: ```bash RACK_ATTACK_REQ_IP_LIMIT=300 # general requests per IP RACK_ATTACK_REQ_IP_PERIOD=300 # ...per 5 minutes RACK_ATTACK_LOGIN_LIMIT=10 # login attempts RACK_ATTACK_LOGIN_PERIOD=60 # ...per minute RACK_ATTACK_FAILED_LOGIN_LIMIT=5 # failed logins before lockout RACK_ATTACK_FAILED_LOGIN_PERIOD=20 RACK_ATTACK_FAILED_LOGIN_TTL=300 ``` Failed-login throttling can vary by account as well as by IP, which blunts credential-stuffing that rotates source addresses. Optional GeoIP blocking can refuse traffic from configured countries. Crucially, the Rack::Attack cache is **[fail-open](/architecture/redis-resilience/)**. If the backing store is unavailable, requests are allowed through rather than rejected — a throttling outage must not become a site outage. ## Level 2 — application limits with OrderRateLimiter HTTP throttling is blunt: it counts requests, not meaning. `OrderRateLimiter` adds a precise, business-aware limit on order creation — how many orders a given user may place in a window — independent of how many HTTP requests that took. It is backed by **Solid Cache** (PostgreSQL), not Redis. That is deliberate: order limiting is a correctness control, so it runs on the same durable store as the orders themselves, with no dependency on the cache tier being up. ## Why two levels | | Rack::Attack | OrderRateLimiter | |--|--------------|------------------| | Sits | In middleware, pre-controller | In the order-creation path | | Counts | HTTP requests, by IP/account | Domain actions, by user | | Store | Redis (fail-open) | PostgreSQL (durable) | | Stops | Floods, brute force, scrapers | Order abuse, retries, gaming | One catches the cheap, high-volume attacks early; the other enforces a rule that only makes sense in terms of the domain. Together they keep the expensive endpoints available for the shoppers who are using them legitimately. ## Key files | Concern | Files | |---------|-------| | HTTP layer | `config/initializers/rack_attack.rb`, `RACK_ATTACK_*` env vars | | App layer | `OrderRateLimiter`, `EmailSendRateLimiter`, `RazorpayRateLimiter` | | Geo | `GeoIpService` |