What's New in v2.5

v2.5.0 makes rate limits and AuthShield lockouts hold when your application runs as more than one instance. Full details are in CHANGELOG.md.

Limits that hold across replicas

Before v2.5, rate-limit counters and AuthShield's failed-login counts lived in each process. Behind a load balancer with N instances, a client got N times every limit, and N times the failed logins before a lockout. Config.Counters now takes a shared store:

1import (
2 "github.com/MUKE-coder/sentinel/v2/redisstore"
3 "github.com/redis/go-redis/v9"
4)
5
6client := redis.NewClient(&redis.Options{Addr: "redis:6379"})
7
8sentinel.Mount(r, nil, sentinel.Config{
9 Counters: redisstore.New(client),
10 RateLimit: sentinel.RateLimitConfig{
11 Enabled: true,
12 ByIP: &sentinel.Limit{Requests: 100, Window: time.Minute},
13 },
14 AuthShield: sentinel.AuthShieldConfig{Enabled: true, LoginRoute: "/api/login"},
15})

redisstore works with a single Redis server, Redis Sentinel, or a cluster. Each rate-limit decision runs as one Lua script, so two replicas can't both take the last slot. If several applications share one Redis, give each one its own redisstore.WithPrefix.

If Redis goes down

Requests are allowed rather than failed, and the error is logged at most once a minute. Set timeouts on the Redis client so a slow Redis can't hold requests up.

Without Counters, nothing changes: counters stay in memory, as before. Scaling out also needs:

  • shared storage (Postgres)
  • the same Dashboard.SecretKey on every replica
  • WAF.TrustedProxies set to your load balancer

examples/multi-replica in the repository runs two replicas behind Caddy with all of that in place.

Your own counter store

sentinel.CounterStore is an interface. To use something other than Redis, implement it and run the countertest conformance suite from your tests. The in-memory and Redis stores both pass it.

Other changes

  • Credential-stuffing detection counts distinct usernames within LockoutDuration. Before, it counted every username an IP had tried since its last successful login.
  • The dashboard's AuthShield panel lists only IPs with failures or a lockout in the current window.

Built with by JB