Edge proxy
Run a caching reverse proxy as a sidecar next to your application. Verify requests hit localhost, so cache hits return from
local memory and repeat lookups don't reach your database. Other traffic flows through the proxy unchanged to the upstream Ory
Talos server.
How it works
The proxy intercepts only POST /v2alpha1/admin/apiKeys:verify. It caches a response when the upstream returns 200 OK and the
body has is_valid: true. It forwards invalid keys, errors, and every other endpoint — including :batchVerify — transparently
and never caches them.
Verify is an admin endpoint, so the proxy must be reachable with the same admin credentials accepted by upstream. Point your
application's verify URL at the proxy (http://localhost:8080) and send admin and key-management calls directly to upstream.
Configuration
Start the proxy with talos-commercial proxy:
talos-commercial proxy \
--upstream http://talos-central:4420 \
--listen :9090 \
--cache-ttl 60s
| Flag | Default | Description |
|---|---|---|
--upstream | (required) | Upstream Ory Talos server URL. |
--listen | :8080 | Listen address. |
--cache-ttl | 60s | Default TTL for cached verify responses. |
--cache-max-size | 104857600 (100 MB) | Maximum in-memory cache size, as a raw byte count (suffixes like 100MB aren't accepted). |
--cache-num-counters | 10000 | Number of frequency counters for cache admission. Raise for large working sets. |
--trust-x-forwarded-host | false | Use X-Forwarded-Host for tenant-aware cache keys. Enable only behind a trusted proxy. |
--allowed-hosts | (none) | Comma-separated allowlist of valid Host (or X-Forwarded-Host) values. Other hosts → 403. |
Cache behavior
Cache key
The key is SHA256(host, credential) with null-byte-separated, length-prefixed inputs so the host/credential boundary cannot be
forged. The host comes from Host (or X-Forwarded-Host when trusted), giving each tenant its own cache namespace.
TTL
The effective TTL is min(--cache-ttl, time_until_expiry), where time_until_expiry comes from the verify response's
expire_time field when present. If the credential expires within one second, the proxy serves the response but doesn't cache it.
Cache headers
Verify responses that pass through the cache carry an Ory-Talos-Cache header:
HIT— served from local cache.MISS— fetched from upstream (and possibly cached for next time).
Cache bypass
Send Cache-Control: no-cache, Cache-Control: no-store, or Pragma: no-cache to force a fresh upstream call. The proxy doesn't
write bypassed responses back to the cache.
curl -X POST http://localhost:8080/v2alpha1/admin/apiKeys:verify \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TALOS_ADMIN_TOKEN" \
-H "Cache-Control: no-cache" \
-d '{"credential": "sk_live_abc123..."}'
Limits and consistency
The proxy rejects verify request bodies larger than 1 MB with 413 Request Entity Too Large. Revocation takes effect upstream
immediately, but cached results persist for up to --cache-ttl, so pick a TTL that balances latency against revocation
propagation. Clients that need an immediate recheck send Cache-Control: no-cache.
Health checks
| Endpoint | Behavior |
|---|---|
/health/alive | Always returns 200 OK. Use as the liveness probe. |
/health/ready | Calls upstream /health/alive. Returns 200 OK when reachable, 503 Service Unavailable otherwise. Use as readiness. |
/metrics | Prometheus metrics endpoint. |
These three paths bypass --allowed-hosts, so Kubernetes probes hitting the pod IP work without configuring the cluster IP as an
allowed host.
Metrics
The proxy exposes all metrics at /metrics under the talos_proxy_ namespace.
| Metric | Type | Labels | Description |
|---|---|---|---|
talos_proxy_cache_hits_total | Counter | — | Cache hits. |
talos_proxy_cache_misses_total | Counter | — | Cache misses. |
talos_proxy_upstream_requests_total | Counter | status | Requests forwarded to upstream. |
talos_proxy_upstream_latency_seconds | Histogram | — | Latency of upstream requests. |
talos_proxy_request_duration_seconds | Histogram | cached | Total request duration (true/false). |
For broader monitoring guidance, see Metrics.
Sidecar examples
Docker Compose
services:
proxy:
image: oryd/talos-commercial:<version-you-want> # Pin to a specific version; never use latest.
command: proxy --upstream http://talos:4420 --listen :9090 --cache-ttl 60s
ports:
- "9090:9090"
app:
image: your-app:latest
environment:
- TALOS_VERIFY_URL=http://proxy:9090
- TALOS_ADMIN_URL=http://talos:4420
depends_on:
- proxy
This example omits the upstream talos service — see Install Talos for a complete server configuration.
Kubernetes
apiVersion: v1
kind: Pod
metadata:
name: app-with-talos-proxy
spec:
containers:
- name: app
image: your-app:latest
env:
- name: TALOS_VERIFY_URL
value: "http://localhost:9090"
- name: TALOS_ADMIN_URL
value: "http://talos.talos-system.svc.cluster.local:4420"
- name: talos-proxy
image: oryd/talos-commercial:<version-you-want> # Pin to a specific version; never use latest.
args:
- proxy
- --upstream=http://talos.talos-system.svc.cluster.local:4420
- --listen=:9090
ports:
- { containerPort: 9090, name: proxy }
livenessProbe:
httpGet: { path: /health/alive, port: proxy }
readinessProbe:
httpGet: { path: /health/ready, port: proxy }
resources:
requests: { memory: "64Mi", cpu: "50m" }
limits: { memory: "256Mi", cpu: "200m" }
