How Grok2API Handles Session Sticky with a Custom TTL: Implementation Guide
Grok2API implements session sticky by binding each request to a specific credential ID stored with a configurable time-to-live (TTL), ensuring consistent routing across the infrastructure until the entry expires or the credential is revoked.
Grok2API, the open-source API gateway for Grok AI services, uses a sophisticated session sticky mechanism to maintain request affinity with specific credentials. This feature routes user requests consistently to the same account for a configurable duration, preventing unnecessary credential switching and optimizing cache utilization. The implementation supports both in-memory and Redis backends, with TTL enforcement handled at the repository level according to the chenyme/grok2api source code.
Sticky Session Architecture Overview
The sticky session system centers on a repository pattern that abstracts storage operations behind a clean interface, allowing operators to choose between ephemeral memory storage or persistent Redis clusters.
The StickySessionRepository Interface
The core contract is defined in backend/internal/repository/runtime.go. The StickySessionRepository interface specifies three essential operations: Set to store a binding with expiration, Get to retrieve active bindings, and DeleteByAccount to invalidate all entries for a specific account.
Two concrete implementations provide this functionality:
memory.NewStickyStore– In-memory map with manual expiry trackingredis.NewStickyStore– Redis-backed storage utilizing native TTL capabilities
TTL Configuration in RoutingConfig
The sticky duration is configurable via the YAML configuration. In backend/internal/infra/config/config.go, the RoutingConfig struct exposes a StickyTTL field parsed as a Duration type. The selector accesses this value through cfg.Routing.StickyTTL.Value(), passing it during initialization to control how long credentials remain bound to specific request signatures.
How the Selector Implements Sticky Logic
The credential selection logic in backend/internal/application/gateway/selector.go orchestrates the sticky session flow during the request lifecycle.
Sticky Key Generation and Lookup
When processing a request, the selector generates a sticky key using the promptCacheStickyKey function, which derives a unique identifier from the prompt-cache identity. The selector then queries the sticky store:
// Inside selector.go selection flow (lines 135-273)
stickyKey := promptCacheStickyKey(promptCacheKey)
storedID, ok := sticky.Get(ctx, stickyKey, now)
If ok returns true and the stored credential ID matches the candidate, the selector immediately uses that credential without recomputing rankings, ensuring session continuity.
TTL Enforcement and Updates
Upon successful credential selection, the selector updates the sticky entry with a fresh expiration timestamp:
err := sticky.Set(ctx, stickyKey, candidate.Credential.ID, currentTime.Add(stickyTTL))
Both storage backends validate expiration during the Get operation. The selector passes the current time (now) to the store; if the entry has expired, the store returns ok == false, triggering a fresh selection cycle.
Cleanup on Credential Revocation
When credentials are removed or revoked, the selector cleans up orphaned sticky bindings:
sticky.DeleteByAccount(ctx, revokedAccountID)
This ensures that revoked accounts immediately stop receiving traffic, regardless of remaining TTL.
Storage Backends: Memory vs Redis
Grok2API provides two production-ready implementations of the sticky session store, each handling TTL enforcement differently.
In-Memory Store with Expiry Tracking
The memory implementation in backend/internal/infra/runtime/memory/store.go uses a stickyBinding struct containing an expiresAt field. During Get and Set operations, the store filters expired entries by comparing expiresAt against the provided now timestamp, ensuring stale bindings never influence routing decisions.
Redis Implementation with Lua Scripts
The Redis backend in backend/internal/infra/runtime/redis/store.go leverages Redis native TTL for automatic expiration. For account deletion operations, it uses a Lua script (deleteStickyByAccountScript) that iterates through bindings and verifies expiration timestamps before removal, maintaining consistency across distributed instances.
Practical Implementation Examples
Below are concrete implementations demonstrating how to configure and interact with the sticky session system.
Initialize a selector with a 5-minute sticky TTL:
selector := gateway.NewSelector(
accountRepo,
concurrencyLimiter,
stickyStore, // memory.NewStickyStore() or redis.NewStickyStore()
providerRegistry,
5*time.Minute, // stickyTTL
1*time.Second, // cooldownBase
10*time.Second, // cooldownMax
0, // optional capacity wait
)
The selector automatically applies sticky logic during request processing:
candidate, err := selector.Select(ctx, request)
// If a sticky entry exists for the request's prompt-cache key, the same
// credential ID is returned until the TTL expires.
Manually set a sticky session for advanced use cases:
stickyKey := promptCacheStickyKey(promptCacheKey) // builds "sticky:<hash>"
err := stickyStore.Set(ctx, stickyKey, credentialID, time.Now().Add(5*time.Minute))
if err != nil {
// handle error
}
Clear sticky bindings when revoking credentials:
_ = stickyStore.DeleteByAccount(ctx, revokedAccountID)
Summary
- Grok2API implements session sticky through the
StickySessionRepositoryinterface defined inbackend/internal/repository/runtime.go, with concrete implementations in memory and Redis. - The TTL is configurable via
RoutingConfig.StickyTTLinbackend/internal/infra/config/config.goand enforced during the selection process. - The selector in
backend/internal/application/gateway/selector.gogenerates sticky keys from prompt-cache identities, retrieves existing bindings, and updates expiration timestamps after successful requests. - Both storage backends validate expiration during
Getoperations: the memory store checksexpiresAtfields, while Redis relies on native key TTL with Lua script verification for account deletion. - Sticky bindings are automatically cleared when credentials are revoked via
DeleteByAccount.
Frequently Asked Questions
What is the default TTL for sticky sessions in Grok2API?
Grok2API does not hardcode a default TTL; the value is entirely configuration-driven through the routing.stickyTTL YAML setting. The application parses this as a Duration struct and injects it into the selector at startup, requiring operators to explicitly define the sticky window based on their traffic patterns.
How does Grok2API handle expired sticky sessions?
When the selector calls sticky.Get(ctx, stickyKey, now), the underlying store checks the expiration timestamp against the provided now parameter. If the entry has expired, the store returns ok == false, causing the selector to fall back to normal credential ranking and potentially select a new account for subsequent requests.
Can I disable session sticky in Grok2API?
While there is no explicit "disable" flag in the interface, you can effectively disable sticky sessions by setting the stickyTTL configuration to zero or a negative duration. This causes all sticky entries to expire immediately upon creation, forcing the selector to re-evaluate credentials for every request.
What happens to sticky sessions when a credential is revoked?
The selector invokes sticky.DeleteByAccount(ctx, accountID) whenever a credential is removed or revoked. This operation, implemented in both memory and Redis stores, immediately purges all sticky bindings associated with that account ID, ensuring no further requests route to the invalid credential regardless of remaining TTL.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →