Skip to content

[FEATURE] Implement rate limiting using Bucket4j #174

@nanotaboada

Description

@nanotaboada

Problem

The project currently lacks protection against API abuse and excessive request rates. This leads to:

  • Vulnerability to brute-force attacks and DoS attempts
  • Potential resource exhaustion from malicious or misconfigured clients
  • Unfair resource allocation when multiple clients access the API
  • No throttling mechanism to protect backend services and database
  • Difficulty managing costs and capacity planning
  • Poor quality of service for legitimate users during traffic spikes

Without rate limiting, the API is exposed to abuse scenarios that can degrade performance, increase infrastructure costs, and compromise system availability.

Proposed Solution

Integrate Bucket4j as the rate-limiting library for the Spring Boot RESTful API. This will:

  • Provide robust, in-memory rate limiting based on the token bucket algorithm
  • Protect endpoints from excessive requests and abuse patterns
  • Ensure fair resource allocation across API consumers
  • Return standard HTTP 429 (Too Many Requests) responses when limits are exceeded
  • Improve overall system reliability and user experience
  • Enable fine-grained control over request rates per endpoint or client
  • Integrate seamlessly with Spring Boot's filter/interceptor architecture

Suggested Approach

  1. Add Bucket4j dependency

    • Update pom.xml:
    <dependency>
        <groupId>com.bucket4j</groupId>
        <artifactId>bucket4j-core</artifactId>
        <version>8.17.0</version>
    </dependency>
  2. Create rate limit configuration class

    • Create src/main/java/.../config/RateLimitConfig.java:
    • Define rate limit rules (e.g., 10 requests per minute, 100 per hour)
    • Configure bucket capacity and refill strategy
    • Consider different tiers for different endpoint types
  3. Implement rate limiting filter or interceptor

    • Create src/main/java/.../filters/RateLimitFilter.java:
    • Extend OncePerRequestFilter or implement HandlerInterceptor
    • Extract client identifier (IP address, API key, or user ID)
    • Maintain ConcurrentHashMap<String, Bucket> for in-memory bucket storage
    • Check bucket consumption before processing request
    • Return HTTP 429 with Retry-After header when limit exceeded
  4. Apply rate limiting to controllers

    • Protect public endpoints in BooksController
    • Consider different limits for read vs. write operations
    • Option A: Apply filter globally via FilterRegistrationBean
    • Option B: Use custom annotation + AOP for selective rate limiting
  5. Configure rate limit headers

    • Add standard rate limit response headers:
      • X-RateLimit-Limit: Maximum requests allowed
      • X-RateLimit-Remaining: Remaining requests in current window
      • X-RateLimit-Reset: Time when the rate limit resets
      • Retry-After: Seconds until next request is allowed (on 429)
  6. Add observability and logging

    • Log rate limit events using SLF4J
    • Include client identifier, endpoint, and timestamp
    • Consider metrics integration for monitoring (future enhancement)
  7. Externalize configuration

    • Move rate limit values to application.properties:
    ratelimit.enabled=true
    ratelimit.requests-per-minute=10
    ratelimit.requests-per-hour=100
  8. Key files to modify/create

    • pom.xml - Add Bucket4j dependency
    • src/main/java/.../config/RateLimitConfig.java - Rate limit configuration
    • src/main/java/.../filters/RateLimitFilter.java - Rate limiting filter
    • src/main/resources/application.properties - Rate limit settings
    • src/test/java/.../filters/RateLimitFilterTests.java - Filter unit tests
    • src/test/java/.../controllers/BooksControllerTests.java - Update integration tests
    • README.md - Document rate limiting behavior and configuration
  9. Testing strategy

    • Unit test the filter with mocked buckets
    • Integration test controller endpoints with rapid requests
    • Verify HTTP 429 status and headers
    • Test bucket refill behavior over time
    • Validate that legitimate traffic passes through
  10. Documentation updates

    • Update API documentation (OpenAPI/Swagger) with rate limit info
    • Add rate limiting section to README.md
    • Document configuration options and customization
    • Include examples of rate limit responses

Acceptance Criteria

  • Bucket4j dependency is added to the project
  • Rate limiting filter/interceptor is implemented and registered
  • At least one public endpoint (GET /books) is protected with rate limiting
  • HTTP 429 (Too Many Requests) is returned when rate limit is exceeded
  • Response includes standard rate limit headers (X-RateLimit-*, Retry-After)
  • Client identification uses IP address from request
  • Rate limit configuration is externalized to application.properties
  • Buckets are stored in-memory using ConcurrentHashMap
  • Rate limit events are logged with client identifier and timestamp
  • Unit tests validate filter behavior with bucket consumption
  • Integration tests verify rate limiting on protected endpoints
  • Tests confirm bucket refill works correctly after cooldown period
  • OpenAPI/Swagger documentation reflects rate limiting behavior
  • README.md includes rate limiting configuration guide
  • Application starts successfully with rate limiting enabled
  • Rate limiting can be disabled via configuration flag

References

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestjavaPull requests that update Java code

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions