Use this file to discover all available pages before exploring further.
RiftRelay automatically tracks rate limits from Riot API response headers and uses them to pace future requests. This prevents rate limit violations while maximizing throughput.
RiftRelay maintains rate limit state in rateState (internal/limiter/state.go:12):
type rateState struct { windows []limitWindow // Active rate limit windows blockedUntil time.Time // When to resume after 429 lastGranted time.Time // Last request time (for pacing)}type limitWindow struct { limit int // Max requests in window used int // Requests used so far window time.Duration // Window duration resetAt time.Time // When window resets}
Updates windows: Replaces limit windows with new values from headers
Syncs usage counts: Sets used to the count from headers
Preserves local state: If a window is still active and local used is higher, keep the local value
Applies retry blocking: If this is a 429 response, set blockedUntil to the Retry-After time
func (s *rateState) apply(windows []parsedWindow, retryAfter *time.Time, applyRetry bool, ...) { if len(windows) > 0 { // Build map of existing windows existing := make(map[time.Duration]limitWindow) for _, w := range s.windows { existing[w.window] = w } // Create updated windows for _, parsed := range windows { next := limitWindow{ limit: parsed.limit, used: parsed.count, window: parsed.window + additionalWindow, resetAt: now.Add(parsed.window + additionalWindow), } // Keep higher usage count if window still active if old, ok := existing[next.window]; ok && old.resetAt.After(now) { if old.used > next.used { next.used = old.used } next.resetAt = old.resetAt } } } // Apply 429 blocking if applyRetry && retryAfter != nil { s.blockedUntil = *retryAfter }}
RiftRelay adds ADDITIONAL_WINDOW_SIZE (default 150ms) to rate limit windows as a safety buffer. This accounts for network latency and clock drift. See internal/limiter/state.go:105.
The parseRetryAfter function (internal/limiter/headers.go:16) supports both formats:Seconds format:
Retry-After: 30
HTTP date format:
Retry-After: Wed, 21 Oct 2026 07:28:00 GMT
When a 429 is received:
The blockedUntil time is set based on Retry-After
The X-Rate-Limit-Type header determines whether to block app-level or method-level requests
All subsequent admission checks for that key/region or key/bucket are blocked until blockedUntil
If a 429 doesn’t include X-Rate-Limit-Type, RiftRelay assumes it’s an application-level rate limit and blocks all requests in that region. See internal/limiter/limiter.go:202.
If RiftRelay hasn’t received headers for a region yet, it uses default application limits configured via DEFAULT_APP_RATE_LIMIT (default: 20:1,100:120).See internal/limiter/limiter.go:86 for initialization:
defaultApp := parseRateHeader(cfg.DefaultAppLimits, "")for i := range keys { keys[i] = newKeyState(defaultApp)}
Method limits have no defaults. They’re learned from the first response to each endpoint pattern.