caching¶
The caching section enables a simple in-memory exact-match response cache.
Fields¶
| Field | Type | Default | Notes |
|---|---|---|---|
enabled |
bool | false |
master switch |
ttl |
duration | 1h |
cache entry lifetime |
max_size |
integer | 1000 |
max number of cached entries |
max_entry_bytes |
integer | 16777216 |
maximum retained size of one key and response (16 MiB) |
max_bytes |
integer | 67108864 |
maximum retained size across all entries (64 MiB) |
Example¶
What kind of cache this is¶
This is not semantic caching. It is a straightforward in-memory cache keyed from the complete canonical client JSON, its normalized request, the resolved provider, the target's effective model and upstream protocol, and selected upstream control headers. Requests that differ in output-affecting controls such as stop, response_format, penalties, logit_bias, seed, reasoning effort, or tool configuration do not share an entry. Provider feature and idempotency headers that can affect the result (OpenAI-Beta, Anthropic-Beta, and Idempotency-Key) also participate in the key.
The effective model is resolved in this order: the route target's model, the
request model for that provider, and then the provider's default_model.
LunarGate uses the same effective-model calculation for lookup and storage. If
a fallback target succeeds with a different model, its response is retained
only under that fallback model's key; it cannot satisfy a later lookup for the
primary model.
Eligible requests¶
LunarGate caches only successful responses from operations that are safe to replay:
- non-streaming
POST /v1/chat/completionsrequests that do not explicitly includestore POST /v1/embeddingsrequests
The following always bypass response caching:
- every
POST /v1/responsescreate, includingstore: false - streaming requests
- Chat Completions requests with an explicit
store: trueorstore: false - stored Chat Completions, Responses lifecycle, Conversations, cancellation, compaction, input-token counting, and every other state-changing operation
An explicit storage policy is itself a side-effect contract. Serving store: true from cache would skip creation of the upstream object, while retaining a store: false result in the response cache would violate the caller's requested storage policy.
Use it when:
- prompts repeat often
- responses are deterministic enough for your use case
- a single gateway instance handling repeated traffic is enough
Practical guidance¶
- Keep it off if you are still validating routing behavior and want every request to hit the provider.
- Use
X-LunarGate-No-Cache: truefor request-level cache bypass when needed. - Both the entry-count and total-byte limits apply at the same time. LunarGate evicts the oldest entries until a new response fits both limits.
- Byte accounting includes the cache key and retained serialized response buffers; it intentionally excludes fixed Go object overhead. A response larger than
max_entry_bytesis served normally but is not retained.max_entry_bytesmust not exceedmax_bytes. - Remember that this cache is process-local and disappears on restart.
Hot reload behavior¶
Reloading an effectively identical caching section preserves unexpired entries. Changing any cache setting replaces the cache configuration and clears all existing entries so values retained under different TTL or capacity semantics are not reused.
Provider reloads use a separate safeguard. If a provider definition changes, LunarGate rotates an opaque process-local cache namespace for that provider alias. Requests already in flight may finish with the previous provider generation, but their later cache writes cannot be read by requests using the new account, endpoint, credentials, translator settings, or model configuration. Unchanged provider aliases retain their namespace and can continue using otherwise eligible entries.