- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
8.9 KiB
RateLimit to SlidingWindow Migration Guide
This guide explains how to migrate from the legacy RateLimit implementation to the new SlidingWindow-based system.
Overview
The RateLimit module has been refactored to use the SlidingWindow module for better performance, accuracy, and advanced analytics. The new implementation provides:
- Improved Accuracy: True sliding window instead of fixed windows
- Advanced Analytics: Burst detection, threat analysis, and pattern recognition
- Better Performance: Optimized data structures and caching
- Unified Architecture: Consistent with other framework modules
Key Changes
1. New Classes
SlidingWindowRateLimiter: Modern rate limiter using SlidingWindowSlidingWindowTokenBucket: Token bucket with analyticsRateLimitAggregator: Advanced analytics aggregatorRateLimitResult: Enhanced result object (already existing)
2. Backwards Compatibility
The old RateLimiter class is still available and functional. No breaking changes to existing API.
Migration Steps
Step 1: Update Dependency Injection
// Old way (still works)
$rateLimiter = $container->get(RateLimiter::class);
// New way (recommended)
$rateLimiter = $container->get(SlidingWindowRateLimiter::class);
// Or use alias
$rateLimiter = $container->get('rate_limiter'); // Points to SlidingWindow version
Step 2: Basic Rate Limiting Migration
// Old implementation
$rateLimiter = new RateLimiter(new CacheStorage($cache));
$result = $rateLimiter->checkLimit('user:123', 10, 60);
// New implementation
$windowFactory = new SlidingWindowFactory($cache);
$rateLimiter = new SlidingWindowRateLimiter($windowFactory);
$result = $rateLimiter->checkLimit('user:123', 10, 60);
// API is identical, but implementation is more accurate
Step 3: Enhanced Analytics (New Feature)
// New advanced analytics capability
$requestContext = [
'client_ip' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'request_path' => $_SERVER['REQUEST_URI']
];
$result = $rateLimiter->checkLimitWithAnalysis('user:123', 10, 60, $requestContext);
// Check for security threats
if ($result->isAttackSuspected()) {
// Handle potential attack
$threatLevel = $result->getThreatLevel(); // 'low', 'medium', 'high', 'critical'
$patterns = $result->attackPatterns; // ['burst_attack', 'volumetric_attack']
}
// Check for anomalous traffic
if ($result->hasAnomalousTraffic()) {
$deviation = $result->baselineDeviation;
// Implement adaptive response
}
Step 4: Token Bucket Migration
// Old token bucket (through RateLimiter)
$result = $rateLimiter->checkTokenBucket('api:service', 100, 10, 5);
// New dedicated token bucket with analytics
$tokenBucket = new SlidingWindowTokenBucket(
identifier: 'api:service',
capacity: 100,
refillRate: 10,
windowFactory: $windowFactory
);
$result = $tokenBucket->consumeWithAnalysis(5, $requestContext);
Step 5: Update Middleware/Controllers
class RateLimitMiddleware
{
public function __construct(
// Old
// private RateLimiter $rateLimiter
// New
private SlidingWindowRateLimiter $rateLimiter
) {}
public function handle($request, $next)
{
$clientId = $this->getClientId($request);
// Enhanced with threat analysis
$result = $this->rateLimiter->checkLimitWithAnalysis(
$clientId,
100,
300,
[
'client_ip' => $request->getClientIp(),
'user_agent' => $request->getUserAgent(),
'request_path' => $request->getPath()
]
);
if (!$result->isAllowed()) {
return $this->createRateLimitResponse($result);
}
// Log security events
if ($result->shouldLogSecurityEvent()) {
$this->logSecurityEvent($result);
}
return $next($request);
}
}
Configuration Changes
Environment Variables
No changes to existing environment variables. New optional variables:
# SlidingWindow-specific settings
RATE_LIMIT_PERSISTENT=true
RATE_LIMIT_BURST_THRESHOLD=0.8
RATE_LIMIT_MIN_INTERVAL_THRESHOLD=2.0
# Advanced analytics
RATE_LIMIT_THREAT_ANALYSIS_ENABLED=true
RATE_LIMIT_BASELINE_TRACKING_ENABLED=true
Container Configuration
// In your service provider or bootstrap
$container->bind(SlidingWindowRateLimiter::class, function ($container) {
$cache = $container->get(Cache::class);
$windowFactory = new SlidingWindowFactory($cache);
return new SlidingWindowRateLimiter(
$windowFactory,
persistent: $_ENV['RATE_LIMIT_PERSISTENT'] ?? true
);
});
Performance Improvements
Memory Usage
- Reduced: Optimized data structures in SlidingWindow module
- Efficient: Smart cleanup of expired data
Processing Speed
- Faster: Batch operations and optimized algorithms
- Scalable: Better performance under high load
Accuracy
- Precise: True sliding window vs. fixed window approximation
- Consistent: Uniform distribution of requests over time
New Features
1. Burst Detection
$analytics = $rateLimiter->getAdvancedAnalytics('user:123', 60);
if ($analytics['burst_analysis']['burst_detected']) {
// Handle burst attack
}
2. Threat Analysis
$result = $rateLimiter->checkLimitWithAnalysis($key, $limit, $window, $context);
$threatScore = $result->threatScore->getValue(); // 0-100
$recommendedActions = $result->getRecommendedStrategy();
3. Adaptive Responses
// Automatically adjusts retry-after based on patterns
$retryAfter = $result->adaptiveRetryAfter->toSeconds();
// Multiple response strategies
foreach ($result->responseStrategies as $strategy) {
match ($strategy) {
'immediate_block' => $this->blockImmediately(),
'enhanced_monitoring' => $this->enableMonitoring(),
'captcha_challenge' => $this->requireCaptcha(),
};
}
Testing Migration
Unit Tests
class SlidingWindowRateLimiterTest extends TestCase
{
public function test_basic_rate_limiting()
{
$cache = new InMemoryCache();
$windowFactory = new SlidingWindowFactory($cache);
$rateLimiter = new SlidingWindowRateLimiter($windowFactory);
// Test basic functionality
$result = $rateLimiter->checkLimit('test', 5, 60);
$this->assertTrue($result->isAllowed());
}
public function test_threat_detection()
{
// Test burst pattern detection
// Test anomaly detection
// Test attack pattern recognition
}
}
Integration Tests
class RateLimitIntegrationTest extends TestCase
{
public function test_middleware_integration()
{
// Test with actual HTTP requests
// Test threat detection in middleware
// Test performance under load
}
}
Monitoring and Observability
Metrics to Track
// Basic metrics (existing)
- rate_limit_requests_allowed
- rate_limit_requests_blocked
- rate_limit_processing_time
// New metrics
- rate_limit_threats_detected
- rate_limit_burst_patterns
- rate_limit_baseline_deviations
- rate_limit_adaptive_responses
Logging
// Enhanced logging with threat context
if ($result->shouldLogSecurityEvent()) {
$logger->warning('Rate limit security event', [
'client_ip' => $result->clientIp,
'threat_level' => $result->getThreatLevel(),
'attack_patterns' => $result->attackPatterns,
'recommended_actions' => $result->getRecommendedStrategy()
]);
}
Rollback Plan
If issues arise, you can easily rollback:
-
Switch DI binding:
// Change from $container->bind('rate_limiter', SlidingWindowRateLimiter::class); // Back to $container->bind('rate_limiter', RateLimiter::class); -
Update middleware: Change constructor injection back to
RateLimiter -
Remove new features: Comment out threat analysis code
The old implementation remains fully functional and tested.
Timeline
Phase 1: Preparation (Week 1)
- Update DI container configuration
- Deploy alongside old implementation
- Update monitoring
Phase 2: Gradual Migration (Week 2-3)
- Migrate non-critical endpoints
- Monitor performance and accuracy
- Test threat detection
Phase 3: Full Migration (Week 4)
- Migrate critical endpoints
- Enable advanced analytics
- Full monitoring deployment
Phase 4: Optimization (Week 5)
- Fine-tune threat detection thresholds
- Optimize performance based on metrics
- Remove old implementation if stable
Support
For questions or issues during migration:
- Check existing unit tests for usage examples
- Review the
Examples/SlidingWindowRateLimitExample.phpfile - Consult the SlidingWindow module documentation
- Test thoroughly in staging environment
The migration is designed to be gradual and safe, with full backwards compatibility maintained.