Dynamic and Adaptive Rate Limiting

Dynamic and Adaptive Rate Limiting

Static rate limits often prove either too restrictive for legitimate users or too permissive for preventing abuse. Dynamic rate limiting adjusts limits based on various factors including user tier, API endpoint, time of day, and system load. This flexibility enables optimal resource utilization while maintaining security.

// Java Spring Boot example of dynamic rate limiting
@Component
public class DynamicRateLimiter {
    
    private final Map<String, RateLimitConfig> endpointConfigs = new HashMap<>();
    private final Map<String, UserTier> userTiers = new HashMap<>();
    
    @PostConstruct
    public void initialize() {
        // Configure endpoint-specific limits
        endpointConfigs.put("/api/search", new RateLimitConfig(10, 60)); // 10/minute
        endpointConfigs.put("/api/export", new RateLimitConfig(5, 3600)); // 5/hour
        endpointConfigs.put("/api/webhook", new RateLimitConfig(100, 60)); // 100/minute
        
        // Configure user tiers
        userTiers.put("basic", new UserTier(1.0));
        userTiers.put("premium", new UserTier(10.0));
        userTiers.put("enterprise", new UserTier(100.0));
    }
    
    public RateLimitDecision checkRateLimit(String userId, String endpoint) {
        RateLimitConfig config = endpointConfigs.getOrDefault(endpoint, 
            new RateLimitConfig(100, 3600));
        
        UserTier tier = getUserTier(userId);
        double multiplier = tier.getMultiplier();
        
        // Adjust limits based on system load
        double loadMultiplier = getSystemLoadMultiplier();
        
        int effectiveLimit = (int) (config.getLimit() * multiplier * loadMultiplier);
        
        return applyRateLimit(userId, endpoint, effectiveLimit, config.getWindow());
    }
    
    private double getSystemLoadMultiplier() {
        double cpuUsage = getCPUUsage();
        double memoryUsage = getMemoryUsage();
        
        // Reduce limits when system is under stress
        if (cpuUsage > 0.8 || memoryUsage > 0.8) {
            return 0.5;
        } else if (cpuUsage > 0.6 || memoryUsage > 0.6) {
            return 0.75;
        }
        return 1.0;
    }
    
    @Data
    @AllArgsConstructor
    static class RateLimitConfig {
        private int limit;
        private int window; // seconds
    }
    
    @Data
    @AllArgsConstructor
    static class UserTier {
        private double multiplier;
    }
}

@RestController
@Slf4j
public class APIController {
    
    @Autowired
    private DynamicRateLimiter rateLimiter;
    
    @GetMapping("/api/**")
    public ResponseEntity<?> handleRequest(
            HttpServletRequest request,
            @RequestHeader("X-API-Key") String apiKey) {
        
        String userId = getUserIdFromApiKey(apiKey);
        String endpoint = request.getRequestURI();
        
        RateLimitDecision decision = rateLimiter.checkRateLimit(userId, endpoint);
        
        if (!decision.isAllowed()) {
            return ResponseEntity.status(429)
                .header("Retry-After", String.valueOf(decision.getRetryAfter()))
                .body(Map.of(
                    "error", "Rate limit exceeded",
                    "limit", decision.getLimit(),
                    "window", decision.getWindow(),
                    "retryAfter", decision.getRetryAfter()
                ));
        }
        
        // Process request...
    }
}

Machine learning can enhance rate limiting by identifying abnormal patterns that static rules miss. Train models on historical API usage to establish baseline behaviors for different client types. Detect anomalies like sudden spikes in request volume, unusual endpoint access patterns, or requests from new geographic locations. Use these signals to dynamically adjust rate limits or trigger additional security measures.