Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introducing the new Rate Limiter component

Introducing the new Rate Limiter component

Short presentation about the new Rate Limiter component in Symfony 5.2.

See https://github.com/malteschlueter/demo-rate-limiter for implementation examples.

Avatar for Malte Schlüter

Malte Schlüter

January 05, 2021
Tweet

More Decks by Malte Schlüter

Other Decks in Programming

Transcript

  1. Why you want to use it? → Limit requests in

    a specific time → Set different request limitations for authenticated users → Limit it like you implement it Malte Schlüter
  2. Fixed Window Set a limit for a given interval of

    time, like → 5.000 requests per hour → 3 login attempts every 15 minutes Malte Schlüter
  3. Fixed Window Example of a problem → 5.000 requests per

    hour are allowed → A user makes 5.000 requests in the last minute of some hour → And 5.000 requests during the first minute of the next hour → Making 10.000 requests in total in 2 minutes → Possibly the server will overloading Malte Schlüter 4.999 4.999 1 req
  4. Sliding Window → Alternative to the Fixed Window algorithm →

    Designed to reduce bursts → The rate limit is calculated based on the current window and the previous window Malte Schlüter
  5. Sliding Window Example → 5.000 requests per hour are allowed

    → A user makes 4.000 requests the previous hour and 0 requests this hour → At the beginning of this hour there are 1.000 remaining requests → 5.000 - 100% * 4.000 = 1.000 Malte Schlüter
  6. Sliding Window Example → 5.000 requests per hour are allowed

    → A user makes 4.000 requests the previous hour and 0 requests this hour → 15 minutes in to the current hour are 25% of the window → Remaining requests are actual 2.000 requests → 5.000 - 75% * 4.000 = 2.000 Malte Schlüter
  7. Sliding Window Example → 5.000 requests per hour are allowed

    → A user makes 4.000 requests the previous hour and 0 requests this hour → 30 minutes in to the current hour are 50% of the window → Remaining requests are actual 3.000 requests → 5.000 - 50% * 4.000 = 3.000 Malte Schlüter
  8. Sliding Window Example → 5.000 requests per hour are allowed

    → A user makes 4.000 requests the previous hour and 500 requests this hour → 30 minutes in to the current hour are 50% of the window → Remaining requests are actual 2.500 requests → 5.000 - 50% * 4.000 - 500 = 2.500 Malte Schlüter
  9. Sliding Window Example → 5.000 requests per hour are allowed

    → A user makes 4.000 requests the previous hour and 500 requests this hour → 15 minutes in to the current hour are 25% of the window → Remaining requests are actual 1.500 requests → 5.000 - 75% * 4.000 - 500 = 1.500 Malte Schlüter
  10. Token Bucket → A bucket is created with an initial

    set of tokens → A new token is added to the bucket with a predefined frequency (e.g. every second) → If the bucket still contains tokens, the event is allowed; otherwise, it’s denied → If the bucket is at full capacity, new tokens are discarded Malte Schlüter
  11. Configuration Example # config/packages/rate_limiter.yaml framework: rate_limiter: anonymous_api: policy: 'sliding_window' limit:

    100 interval: '60 minutes' authenticated_api: policy: 'token_bucket' limit: 5000 rate: { interval: '15 minutes', amount: 500 } Malte Schlüter
  12. How to implement? class AnonymousLimiterController { public function __construct( private

    RateLimiterFactory $anonymousApiLimiter ) {} // ... } # config/packages/rate_limiter.yaml framework: rate_limiter: anonymous_api: policy: 'sliding_window' limit: 100 interval: '60 minutes' authenticated_api: policy: 'token_bucket' limit: 5000 rate: { interval: '15 minutes', amount: 500 } Malte Schlüter
  13. How to implement? class AnonymousLimiterController { public function __construct( private

    RateLimiterFactory $anonymousApiLimiter ) {} #[Route('/anonymous', name: 'app_anonymous_limiter')] public function __invoke(Request $request): Response { $limiter = $this->anonymousApiLimiter->create($request->getClientIp()); if (!$limiter->consume()->isAccepted()) { return new JsonResponse(['status' => 'error'], Response::HTTP_TOO_MANY_REQUESTS); } return new JsonResponse(['status' => 'ok']); } } Malte Schlüter
  14. How to implement? class AnonymousLimiterController { public function __construct( private

    RateLimiterFactory $authenticatedApiLimiter ) {} #[Route('/anonymous', name: 'app_anonymous_limiter')] public function __invoke(Request $request): Response { $limiter = $this->authenticatedApiLimiter->create($request->headers->get('application_key')); $limiter->reserve()->wait(); return new JsonResponse(['status' => 'ok']); } } Malte Schlüter