English | 한국어
FluxGate is a production-ready, distributed rate limiting framework for Java applications. Built on top of Bucket4j, it provides enterprise-grade features including Redis-backed distributed rate limiting, MongoDB rule management, and seamless Spring Boot integration.
- Distributed Rate Limiting - Redis-backed token bucket algorithm with atomic Lua scripts
- Multi-Band Support - Multiple rate limit tiers (e.g., 100/sec + 1000/min + 10000/hour)
- Dynamic Rule Management - Store and update rules in MongoDB without restart
- Spring Boot Auto-Configuration - Zero-config setup with sensible defaults
- LimitScope-based Key Resolution - Rate limit by IP, User ID, API Key, or custom composite keys
- Composite Key Support - Combine multiple identifiers (e.g., IP + User ID) for fine-grained control
- WAIT_FOR_REFILL Policy - Wait for token refill instead of immediate rejection
- RequestContext Customization - Override client IP, add custom attributes before rate limiting
- Multiple Filters Support - Configure multiple filters with different priorities via Java Config
- Production-Safe Design - Uses Redis server time (no clock drift), integer arithmetic only
- HTTP API Mode - Centralized rate limiting service via REST API
- Pluggable Architecture - Easy to extend with custom handlers and stores
- Structured Logging - JSON logging with correlation IDs for ELK/Splunk integration
- Prometheus Metrics - Built-in Micrometer integration for monitoring and alerting
┌─────────────────────────────────────────────────────────────────────────┐
│ FluxGate Architecture │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ Client │───▶│ Spring Boot │───▶│ FluxGate Filter │ │
│ │ Application │ │ Application │ │ (Auto Rate Limiting) │ │
│ └──────────────┘ └──────────────┘ └───────────┬──────────────┘ │
│ │ │
│ ┌───────────────────────────────┼───────────────┐ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ RateLimitHandler │ │ │
│ │ │ ┌─────────────┐ ┌──────────────────┐ │ │ │
│ │ │ │ Direct │ │ HTTP API │ │ │ │
│ │ │ │ Redis │ │ (REST Call) │ │ │ │
│ │ │ └──────┬──────┘ └────────┬─────────┘ │ │ │
│ │ └─────────┼──────────────────┼────────────┘ │ │
│ │ │ │ │ │
│ └────────────┼──────────────────┼───────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────────────────────┐ ┌────────────────────────┐ │
│ │ Redis │ │ Rate Limit Service │ │
│ │ ┌──────────────────────────────┐ │ │ (fluxgate-sample- │ │
│ │ │ Token Bucket State │ │ │ redis on port 8082) │ │
│ │ │ (Lua Script - Atomic) │ │◀───│ │ │
│ │ └──────────────────────────────┘ │ └────────────────────────┘ │
│ └────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────┐ │
│ │ MongoDB │ │
│ │ ┌──────────────────────────────┐ │ │
│ │ │ Rate Limit Rules │ │ │
│ │ │ (Dynamic Configuration) │ │ │
│ │ └──────────────────────────────┘ │ │
│ └────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
| Module | Description |
|---|---|
| fluxgate-core | Core rate limiting engine with Bucket4j integration |
| fluxgate-redis-ratelimiter | Redis-backed distributed rate limiter with Lua scripts |
| fluxgate-mongo-adapter | MongoDB adapter for dynamic rule management |
| fluxgate-spring-boot3-starter | Spring Boot 3.x auto-configuration (Java 17+, jakarta.servlet) |
| fluxgate-spring-boot2-starter | Spring Boot 2.x auto-configuration (Java 11+, javax.servlet) |
| fluxgate-testkit | Integration testing utilities |
| fluxgate-samples | Sample applications demonstrating various use cases |
- Java 11+
- Maven 3.8+
- Redis 6.0+ (for distributed rate limiting)
- MongoDB 4.4+ (optional, for rule management)
<!-- For Spring Boot 3.x (Java 17+) -->
<dependency>
<groupId>io.github.openfluxgate</groupId>
<artifactId>fluxgate-spring-boot3-starter</artifactId>
<version>0.3.3</version>
</dependency>
<!-- For Spring Boot 2.x (Java 11+) -->
<!--
<dependency>
<groupId>io.github.openfluxgate</groupId>
<artifactId>fluxgate-spring-boot2-starter</artifactId>
<version>0.3.3</version>
</dependency>
-->
<!-- For Redis-backed rate limiting -->
<dependency>
<groupId>io.github.openfluxgate</groupId>
<artifactId>fluxgate-redis-ratelimiter</artifactId>
<version>0.3.3</version>
</dependency>
<!-- For MongoDB rule management (optional) -->
<dependency>
<groupId>io.github.openfluxgate</groupId>
<artifactId>fluxgate-mongo-adapter</artifactId>
<version>0.3.3</version>
</dependency># application.yml
fluxgate:
redis:
enabled: true
uri: redis://localhost:6379
ratelimit:
filter-enabled: true
default-rule-set-id: api-limits
include-patterns:
- /api/*
exclude-patterns:
- /health
- /actuator/*@SpringBootApplication
@EnableFluxgateFilter(handler = HttpRateLimitHandler.class)
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}# Send 12 requests (with 10 req/min limit)
for i in {1..12}; do
curl -s -o /dev/null -w "Request $i: %{http_code}\n" http://localhost:8080/api/hello
done
# Expected output:
# Request 1-10: 200
# Request 11-12: 429 (Too Many Requests)Best for simple deployments where each application instance connects directly to Redis.
┌─────────────┐ ┌─────────────┐
│ App #1 │────▶│ │
├─────────────┤ │ Redis │
│ App #2 │────▶│ │
├─────────────┤ │ │
│ App #N │────▶│ │
└─────────────┘ └─────────────┘
Best for microservices architecture where you want a dedicated rate limiting service.
┌─────────────┐ ┌─────────────────┐ ┌─────────────┐
│ App #1 │────▶│ │ │ │
├─────────────┤ │ Rate Limit │────▶│ Redis │
│ App #2 │────▶│ Service (8082) │ │ │
├─────────────┤ │ │ │ │
│ App #N │────▶│ │ │ │
└─────────────┘ └─────────────────┘ └─────────────┘
# Client application configuration
fluxgate:
api:
url: http://rate-limit-service:8082
ratelimit:
filter-enabled: true| Sample | Port | Description |
|---|---|---|
| fluxgate-sample-standalone | 8085 | Full stack with direct MongoDB + Redis integration |
| fluxgate-sample-redis | 8082 | Rate limit service with Redis backend |
| fluxgate-sample-mongo | 8081 | Rule management with MongoDB |
| fluxgate-sample-filter | 8083 | Client app with auto rate limiting filter |
| fluxgate-sample-api | 8084 | REST API for rate limit checking |
# Start infrastructure
docker-compose up -d redis mongodb
# Start rate limit service
./mvnw spring-boot:run -pl fluxgate-samples/fluxgate-sample-redis
# Start client application (in another terminal)
./mvnw spring-boot:run -pl fluxgate-samples/fluxgate-sample-filter
# Test rate limiting
curl http://localhost:8083/api/hello| Property | Default | Description |
|---|---|---|
fluxgate.redis.enabled |
false |
Enable Redis rate limiter |
fluxgate.redis.uri |
redis://localhost:6379 |
Redis connection URI |
fluxgate.redis.mode |
auto |
Redis mode: standalone, cluster, or auto (auto-detect) |
fluxgate.mongo.enabled |
false |
Enable MongoDB adapter |
fluxgate.mongo.uri |
mongodb://localhost:27017/fluxgate |
MongoDB connection URI |
fluxgate.mongo.database |
fluxgate |
MongoDB database name |
fluxgate.mongo.rule-collection |
rate_limit_rules |
Collection name for rate limit rules |
fluxgate.mongo.event-collection |
- | Collection name for events (optional) |
fluxgate.mongo.ddl-auto |
validate |
DDL mode: validate or create |
fluxgate.ratelimit.filter-enabled |
false |
Enable rate limit filter |
fluxgate.ratelimit.default-rule-set-id |
default |
Default rule set ID |
fluxgate.ratelimit.include-patterns |
[/api/*] |
URL patterns to rate limit |
fluxgate.ratelimit.exclude-patterns |
[] |
URL patterns to exclude |
fluxgate.ratelimit.wait-for-refill.enabled |
false |
Enable WAIT_FOR_REFILL policy |
fluxgate.ratelimit.wait-for-refill.max-wait-time-ms |
5000 |
Max wait time in milliseconds |
fluxgate.ratelimit.wait-for-refill.max-concurrent-waits |
100 |
Max concurrent waiting requests |
fluxgate.api.url |
- | External rate limit API URL |
fluxgate.metrics.enabled |
true |
Enable Prometheus/Micrometer metrics |
The fluxgate.mongo.ddl-auto property controls how FluxGate handles MongoDB collections:
| Mode | Description |
|---|---|
validate |
(Default) Validates that collections exist. Throws an error if missing. |
create |
Automatically creates collections if they don't exist. |
Example configuration:
fluxgate:
mongo:
enabled: true
uri: mongodb://localhost:27017/fluxgate
database: fluxgate
rule-collection: my_rate_limit_rules # Custom collection name
event-collection: my_rate_limit_events # Optional: enable event logging
ddl-auto: create # Auto-create collectionsRateLimitRule rule = RateLimitRule.builder("api-rule")
.name("API Rate Limit")
.enabled(true)
.scope(LimitScope.PER_IP) // GLOBAL, PER_IP, PER_USER, PER_API_KEY, or CUSTOM
.onLimitExceedPolicy(OnLimitExceedPolicy.REJECT_REQUEST) // or WAIT_FOR_REFILL
.addBand(RateLimitBand.builder(Duration.ofSeconds(1), 10)
.label("10-per-second")
.build())
.addBand(RateLimitBand.builder(Duration.ofMinutes(1), 100)
.label("100-per-minute")
.build())
.ruleSetId("api-limits")
.attribute("tier", "standard") // Custom attributes for tracking
.build();| LimitScope | Key Source | Description |
|---|---|---|
GLOBAL |
"global" |
Single bucket for all requests |
PER_IP |
RequestContext.clientIp |
One bucket per IP address |
PER_USER |
RequestContext.userId |
One bucket per user (set via header) |
PER_API_KEY |
RequestContext.apiKey |
One bucket per API key |
CUSTOM |
attributes.get(keyStrategyId) |
Custom key from RequestContext attributes |
For fine-grained rate limiting by IP and User combination:
// Rule with CUSTOM scope
RateLimitRule rule = RateLimitRule.builder("composite-rule")
.name("IP+User Rate Limit")
.scope(LimitScope.CUSTOM)
.keyStrategyId("ipUser") // Looks up context.attributes.get("ipUser")
.addBand(RateLimitBand.builder(Duration.ofMinutes(1), 10).build())
.build();
// RequestContextCustomizer builds the composite key
@Bean
public RequestContextCustomizer requestContextCustomizer() {
return (builder, request) -> {
String userId = request.getHeader("X-User-Id");
String clientIp = request.getRemoteAddr();
// Build composite key: "192.168.1.100:user-123"
String compositeKey = userId != null ? clientIp + ":" + userId : clientIp;
builder.attribute("ipUser", compositeKey);
return builder;
};
}@Bean
public RequestContextCustomizer requestContextCustomizer() {
return (builder, request) -> {
// Set userId for PER_USER scope
String userId = request.getHeader("X-User-Id");
if (userId != null) {
builder.userId(userId);
}
// Set apiKey for PER_API_KEY scope
String apiKey = request.getHeader("X-API-Key");
if (apiKey != null) {
builder.apiKey(apiKey);
}
// Override client IP from Cloudflare header
String cfIp = request.getHeader("CF-Connecting-IP");
if (cfIp != null) {
builder.clientIp(cfIp);
}
// Add tenant info for CUSTOM scope with keyStrategyId="tenantId"
builder.attribute("tenantId", request.getHeader("X-Tenant-Id"));
return builder;
};
}FluxGate provides comprehensive observability features out of the box.
FluxGate outputs JSON-formatted logs with correlation IDs for easy integration with log aggregation systems like ELK Stack or Splunk.
{
"timestamp": "2025-01-15T10:30:45.123Z",
"level": "INFO",
"logger": "org.fluxgate.spring.filter.FluxgateRateLimitFilter",
"message": "Request completed",
"fluxgate.rule_set": "api-limits",
"fluxgate.rule_id": "rate-limit-rule-1",
"fluxgate.allowed": true,
"fluxgate.remaining_tokens": 9,
"fluxgate.client_ip": "192.168.1.100",
"correlation_id": "abc123-def456"
}Enable structured logging by including logback-spring.xml in your application:
<include resource="org/fluxgate/spring/logback-spring.xml"/>FluxGate automatically exposes Micrometer-based metrics when spring-boot-starter-actuator is on the classpath.
Available Metrics:
| Metric | Type | Description |
|---|---|---|
fluxgate_requests_total |
Counter | Total rate limit requests by endpoint, method, and rule_set |
fluxgate_tokens_remaining |
Gauge | Remaining tokens in the bucket |
Example Prometheus output:
# HELP fluxgate_requests_total FluxGate rate limit counter
# TYPE fluxgate_requests_total counter
fluxgate_requests_total{endpoint="/api/test",method="GET",rule_set="api-limits"} 42.0
# HELP fluxgate_tokens_remaining
# TYPE fluxgate_tokens_remaining gauge
fluxgate_tokens_remaining{endpoint="/api/test",rule_set="api-limits"} 8.0
Configuration:
fluxgate:
metrics:
enabled: true # default: true
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
endpoint:
prometheus:
enabled: true# Clone the repository
git clone https://github.com/OpenFluxGate/fluxgate.git
cd fluxgate
# Build all modules
./mvnw clean install
# Run tests
./mvnw test
# Build without tests
./mvnw clean install -DskipTests- FluxGate Core - Core rate limiting concepts and API
- Redis Rate Limiter - Distributed rate limiting with Redis
- MongoDB Adapter - Dynamic rule management
- Spring Boot Starter - Auto-configuration guide
- Extending FluxGate - Custom implementations
- Contributing Guide - Contribute Guide
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
| Project | Description |
|---|---|
| FluxGate Studio | Web-based admin UI for managing rate limit rules |
- Sliding window rate limiting algorithm
- Prometheus metrics integration
- Redis Cluster support
- Structured JSON logging with correlation IDs
- gRPC API support
- Rate limit quota management UI (FluxGate Studio)
- Circuit breaker integration
This project is licensed under the MIT License - see the LICENSE file for details.
- Bucket4j - The underlying rate limiting library
- Lettuce - Redis client for Java
- Spring Boot - Application framework
FluxGate - Distributed Rate Limiting Made Simple