Skip to main content

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
FlagDefaultDescription
--upstream(required)Upstream Ory Talos server URL.
--listen:8080Listen address.
--cache-ttl60sDefault TTL for cached verify responses.
--cache-max-size104857600 (100 MB)Maximum in-memory cache size, as a raw byte count (suffixes like 100MB aren't accepted).
--cache-num-counters10000Number of frequency counters for cache admission. Raise for large working sets.
--trust-x-forwarded-hostfalseUse 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

EndpointBehavior
/health/aliveAlways returns 200 OK. Use as the liveness probe.
/health/readyCalls upstream /health/alive. Returns 200 OK when reachable, 503 Service Unavailable otherwise. Use as readiness.
/metricsPrometheus 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.

MetricTypeLabelsDescription
talos_proxy_cache_hits_totalCounterCache hits.
talos_proxy_cache_misses_totalCounterCache misses.
talos_proxy_upstream_requests_totalCounterstatusRequests forwarded to upstream.
talos_proxy_upstream_latency_secondsHistogramLatency of upstream requests.
talos_proxy_request_duration_secondsHistogramcachedTotal 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" }