# High-level architecture

The basic idea of rate limiting algorithms is simple. At the high-level, we need a counter to keep track of how many requests are sent from the same user, IP address, etc. If the counter is larger than the limit, the request is disallowed. Where shall we store counters? Using the database is not a good idea due to slowness of disk access. In-memory cache is chosen because it is fast and supports time-based expiration

strategy. For instance, Redis is a popular option to implement rate limiting. It is an in-memory store that offers two commands: INCR and EXPIRE.

* INCR: It increases the stored counter by 1.&#x20;
* EXPIRE: It sets a timeout for the counter. If the timeout expires, the counter is automatically deleted.



<figure><img src="https://1722711354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwNXdoUkfmcozr29fRrfb%2Fuploads%2FFDTVCQEZj5Let9j4A9tR%2FScreenshot%202023-11-02%20at%2000.19.57.png?alt=media&#x26;token=26851ae2-0172-442b-b984-83b86401afb5" alt=""><figcaption></figcaption></figure>



* The client sends a request to rate-limiting middleware.&#x20;
* Rate-limiting middleware fetches the counter from the corresponding bucket in Redis and checks if the limit is reached or not.&#x20;
  * If the limit is reached, the request is rejected.&#x20;
  * If the limit is not reached, the request is sent to API servers. Meanwhile, the system increments the counter and saves it back to Redis.
