Skip to content

Latest commit

 

History

History
113 lines (87 loc) · 3.39 KB

File metadata and controls

113 lines (87 loc) · 3.39 KB

Limitly — Developer Usage Guide

Limitly is a production-grade, zero-config Spring Boot starter library for Redis-backed rate limiting. It provides annotation-driven request throttling with atomic Lua execution on Redis.


🚀 Quick Usage Walkthrough

1. Add Configuration (application.yml)

Configure Redis host details and rate limiter defaults in your Spring Boot application's application.yml:

spring:
  data:
    redis:
      host: localhost
      port: 6379

rate-limiter:
  enabled: true
  default-strategy: SLIDING_WINDOW # Options: SLIDING_WINDOW | TOKEN_BUCKET
  default-key-resolver: USER        # Options: USER | IP | SPEL
  fallback-mode: FAIL_OPEN         # Options: FAIL_OPEN | FAIL_CLOSED
  redis:
    key-prefix: "ratelimit:"
  response:
    status: 429
    body: '{"error": "rate_limit_exceeded", "message": "Too many requests. Please try again later."}'
    include-retry-after-header: true
  metrics:
    enabled: true

2. Annotate Controller Methods (@RateLimit)

Drop the @RateLimit annotation directly on your REST endpoints:

Example A: Sliding Window Log (Exact Request Count)

Restricts users to 5 requests per 10 seconds using a Redis Sorted Set (ZSET).

@RestController
@RequestMapping("/api")
public class ProductController {

    @GetMapping("/products/search")
    @RateLimit(limit = 5, window = "10s", strategy = Algorithm.SLIDING_WINDOW)
    public ResponseEntity<?> search(@RequestParam String query) {
        return ResponseEntity.ok(Map.of("query", query));
    }
}

Example B: Token Bucket Algorithm (Allows Micro-Bursts)

Refills continuous tokens per second using a Redis Hash (HMSET).

@PostMapping("/api/ads")
@RateLimit(limit = 10, window = "1m", strategy = Algorithm.TOKEN_BUCKET)
public ResponseEntity<?> createAd() {
    return ResponseEntity.ok("Ad created");
}

Example C: Custom Dynamic Key Resolution with SpEL

Throttles based on client remote IP, custom headers, or session attributes using Spring Expression Language:

@PostMapping("/api/comments")
@RateLimit(key = "#request.remoteAddr", limit = 3, window = "30s")
public ResponseEntity<?> postComment(HttpServletRequest request) {
    return ResponseEntity.ok("Comment posted");
}

Example D: Protect Backend Systems with FAIL_CLOSED

If Redis crashes or suffers network issues, FAIL_CLOSED will block traffic to preserve critical databases.

@PostMapping("/api/checkout")
@RateLimit(limit = 2, window = "5s", onRedisFailure = FallbackMode.FAIL_CLOSED)
public ResponseEntity<?> checkout() {
    return ResponseEntity.ok("Payment processed");
}

⏱️ Window Duration Formats

You can specify duration shorthand strings in the window attribute:

  • "500ms" → 500 milliseconds
  • "10s" → 10 seconds
  • "5m" → 5 minutes
  • "1h" → 1 hour
  • "1d" → 1 day
  • ISO-8601 strings e.g. "PT1M"

📈 Monitoring & Prometheus Metrics

Limitly automatically registers Micrometer metrics when micrometer-core and Spring Boot Actuator are present:

Metric Name Type Description
ratelimiter.requests.allowed Counter Total requests allowed through
ratelimiter.requests.denied Counter Total requests throttled (HTTP 429)
ratelimiter.redis.latency Timer Execution duration of Redis Lua scripts
ratelimiter.redis.failures Counter Count of Redis outage fallback triggers