APILimiter – Request per minute per API key (popular interview question) Java Example

APILimiter.java Main Class

package com.ngdeveloper.api;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class APILimiter {
    private final int defaultRequestPerMinute;
    private final Map<String, TokenBucket> buckets;

    public APILimiter(int defaultRequestPerMinute) {
        this.defaultRequestPerMinute = defaultRequestPerMinute;
        this.buckets = new ConcurrentHashMap<>();
    }

    public void configureRequestsPerMinute(String apiKey, int requestsPerMinute) {
        TokenBucket bucket = buckets.computeIfAbsent(apiKey, key -> new TokenBucket(defaultRequestPerMinute));
        bucket.setTokensPerMinute(requestsPerMinute);
    }

    public boolean allowRequest(String apiKey) {
        TokenBucket bucket = buckets.computeIfAbsent(apiKey, key -> new TokenBucket(defaultRequestPerMinute));
        return bucket.tryConsume();
    }

    private static class TokenBucket {
        private int tokens;
        private Instant lastRefillTime;
        private int tokensPerMinute;

        public TokenBucket(int tokensPerMinute) {
            this.tokens = tokensPerMinute;
            this.lastRefillTime = Instant.now();
            this.tokensPerMinute = tokensPerMinute;
        }

        public synchronized void setTokensPerMinute(int tokensPerMinute) {
            this.tokensPerMinute = tokensPerMinute;
        }

        public synchronized boolean tryConsume() {
            refill();
            if (tokens > 0) {
                tokens--;
                return true;
            } else {
                return false;
            }
        }

        private void refill() {
            Instant now = Instant.now();
            long timeElapsed = now.toEpochMilli() - lastRefillTime.toEpochMilli();
            int tokensToAdd = (int) ((timeElapsed / 1000) * tokensPerMinute / 60);
            tokens = Math.min(tokens + tokensToAdd, tokensPerMinute);
            lastRefillTime = now;
        }
    }

    public static void main(String[] args) {
        // Example usage and testing

        // Create an API limiter with capacity of 60 requests per minute per API key
        APILimiter limiter = new APILimiter(60);

        // Allow some requests for an API key with a limit of 30 requests per minute
        String apiKey1 = "API_KEY_1";
        limiter.configureRequestsPerMinute(apiKey1, 30);
        for (int i = 0; i < 40; i++) {
            boolean allowed = limiter.allowRequest(apiKey1);
            System.out.println("API key 1 request " + (i + 1) + " allowed: " + allowed);
        }

        // Allow some requests for an API key with the default limit of 60 requests per minute
        String apiKey2 = "API_KEY_2";
        for (int i = 0; i < 70; i++) {
            boolean allowed = limiter.allowRequest(apiKey2);
            System.out.println("API key 2 request " + (i + 1) + " allowed: " + allowed);
        }
    }
}

Output:

API key 1 request 1 allowed: true
API key 1 request 2 allowed: true
API key 1 request 3 allowed: true
API key 1 request 4 allowed: true
API key 1 request 5 allowed: true
API key 1 request 6 allowed: true
API key 1 request 7 allowed: true
API key 1 request 8 allowed: true
API key 1 request 9 allowed: true
API key 1 request 10 allowed: true
API key 1 request 11 allowed: true
API key 1 request 12 allowed: true
API key 1 request 13 allowed: true
API key 1 request 14 allowed: true
API key 1 request 15 allowed: true
API key 1 request 16 allowed: true
API key 1 request 17 allowed: true
API key 1 request 18 allowed: true
API key 1 request 19 allowed: true
API key 1 request 20 allowed: true
API key 1 request 21 allowed: true
API key 1 request 22 allowed: true
API key 1 request 23 allowed: true
API key 1 request 24 allowed: true
API key 1 request 25 allowed: true
API key 1 request 26 allowed: true
API key 1 request 27 allowed: true
API key 1 request 28 allowed: true
API key 1 request 29 allowed: true
API key 1 request 30 allowed: true
API key 1 request 31 allowed: false
API key 1 request 32 allowed: false
API key 1 request 33 allowed: false
API key 1 request 34 allowed: false
API key 1 request 35 allowed: false
API key 1 request 36 allowed: false
API key 1 request 37 allowed: false
API key 1 request 38 allowed: false
API key 1 request 39 allowed: false
API key 1 request 40 allowed: false

API key 2 request 1 allowed: true
API key 2 request 2 allowed: true
API key 2 request 3 allowed: true
API key 2 request 4 allowed: true
API key 2 request 5 allowed: true
API key 2 request 6 allowed: true
API key 2 request 7 allowed: true
API key 2 request 8 allowed: true
API key 2 request 9 allowed: true
API key 2 request 10 allowed: true
API key 2 request 11 allowed: true
API key 2 request 12 allowed: true
API key 2 request 13 allowed: true
API key 2 request 14 allowed: true
API key 2 request 15 allowed: true
API key 2 request 16 allowed: true
API key 2 request 17 allowed: true
API key 2 request 18 allowed: true
API key 2 request 19 allowed: true
API key 2 request 20 allowed: true
API key 2 request 21 allowed: true
API key 2 request 22 allowed: true
API key 2 request 23 allowed: true
API key 2 request 24 allowed: true
API key 2 request 25 allowed: true
API key 2 request 26 allowed: true
API key 2 request 27 allowed: true
API key 2 request 28 allowed: true
API key 2 request 29 allowed: true
API key 2 request 30 allowed: true
API key 2 request 31 allowed: true
API key 2 request 32 allowed: true
API key 2 request 33 allowed: true
API key 2 request 34 allowed: true
API key 2 request 35 allowed: true
API key 2 request 36 allowed: true
API key 2 request 37 allowed: true
API key 2 request 38 allowed: true
API key 2 request 39 allowed: true
API key 2 request 40 allowed: true
API key 2 request 41 allowed: true
API key 2 request 42 allowed: true
API key 2 request 43 allowed: true
API key 2 request 44 allowed: true
API key 2 request 45 allowed: true
API key 2 request 46 allowed: true
API key 2 request 47 allowed: true
API key 2 request 48 allowed: true
API key 2 request 49 allowed: true
API key 2 request 50 allowed: true
API key 2 request 51 allowed: true
API key 2 request 52 allowed: true
API key 2 request 53 allowed: true
API key 2 request 54 allowed: true
API key 2 request 55 allowed: true
API key 2 request 56 allowed: true
API key 2 request 57 allowed: true
API key 2 request 58 allowed: true
API key 2 request 59 allowed: true
API key 2 request 60 allowed: true
API key 2 request 61 allowed: false
API key 2 request 62 allowed: false
API key 2 request 63 allowed: false
API key 2 request 64 allowed: false
API key 2 request 65 allowed: false
API key 2 request 66 allowed: false
API key 2 request 67 allowed: false
API key 2 request 68 allowed: false
API key 2 request 69 allowed: false
API key 2 request 70 allowed: false

18 comments

Leave a Reply