TT-6075: Update rate limit implementation #7941
Merged
probelabs / Visor: performance
failed
Apr 20, 2026 in 1m 16s
🚨 Check Failed
performance check failed because fail_if condition was met.
Details
📊 Summary
- Total Issues: 3
- Critical Issues: 2
- Error Issues: 1
🔍 Failure Condition Results
Failed Conditions
- global_fail_if: output.issues && output.issues.some(i => i.severity === 'critical' || i.severity === 'error')
- Severity: ❌ error
Issues by Category
Performance (2)
- 🚨 gateway/session_manager.go:205 - The
limitSentinelfunction spawns a 'fire-and-forget' goroutine for every request to update the Redis rolling window counter. Under high traffic, this can lead to unbounded goroutine creation, causing excessive memory consumption, CPU scheduler contention, and potentially overwhelming the Redis server. This creates a denial-of-service vulnerability where the gateway can be crashed by a flood of requests. - 🚨 gateway/session_manager.go:429 - The key for the in-memory rate-limiting bucket (
bucketKey) is constructed usingsession.LastUpdated. Sincesession.LastUpdatedcan change on every request for certain configurations, a new in-memory bucket may be created for each request when using the default Distributed Rate Limiter (DRL) in single-node mode. This leads to unbounded memory growth as old buckets are never reused or garbage-collected, causing a memory leak that can result in a Denial of Service.
Logic (1)
- ❌ system:0 - Global failure condition met: output.issues && output.issues.some(i => i.severity === 'critical' || i.severity === 'error')
Powered by Visor from Probelabs
💡 TIP: You can chat with Visor using /visor ask <your question>
Annotations
Check failure on line 207 in gateway/session_manager.go
probelabs / Visor: performance
performance Issue
The `limitSentinel` function spawns a 'fire-and-forget' goroutine for every request to update the Redis rolling window counter. Under high traffic, this can lead to unbounded goroutine creation, causing excessive memory consumption, CPU scheduler contention, and potentially overwhelming the Redis server. This creates a denial-of-service vulnerability where the gateway can be crashed by a flood of requests.
Raw output
Replace the "fire-and-forget" goroutine with a managed worker pool. A buffered channel can be used to dispatch update tasks to a fixed number of worker goroutines. This approach controls concurrency, prevents resource exhaustion, and allows for batching or other optimizations.
Check failure on line 432 in gateway/session_manager.go
probelabs / Visor: performance
performance Issue
The key for the in-memory rate-limiting bucket (`bucketKey`) is constructed using `session.LastUpdated`. Since `session.LastUpdated` can change on every request for certain configurations, a new in-memory bucket may be created for each request when using the default Distributed Rate Limiter (DRL) in single-node mode. This leads to unbounded memory growth as old buckets are never reused or garbage-collected, causing a memory leak that can result in a Denial of Service.
Raw output
The bucket key must be deterministic and not based on a volatile, ever-changing value like `session.LastUpdated`. Use a stable identifier from the session, such as the session ID or the base `limiterKey` itself. If a time window is required, use a truncated timestamp (e.g., `time.Now().Unix() / int64(period)`), which remains constant for the duration of the rate limit window.
Loading