Skip to content

Capability coverage ​

What the titanium CLI and its optional Plus add-on cover, by area. Every row links to the page that explains it. Rows marked not supported are listed on purpose, with the reason.

Status: supported works as described. partial works with the limits named in Notes. not supported is not offered; Notes gives the reason and what to use instead.

Config key: a key in twp.yaml, written the way the schema nests it (routes[] is a list entry). A key with a prefix such as plus.options: is a Titanium Plus option, which is a free-form string key. A row with a command, an API path, or a resource name has no twp.yaml key; the cell says what to use. — means there is nothing to set.

Routing ​

CapabilityStatusConfig keyNotesDocs
Match on host, path, method, header, and query, with order and specificitysupportedroutes[].match.hosts, routes[].match.path, routes[].match.pathKind, routes[].orderExact, segment prefix, prefix, template, and regex paths. A lower order wins; ties go to the more specific match.Configuration
Redirects, direct responses, and custom error pagessupportedroutes[].redirect, routes[].directResponse, routes[].errorPagesAnswer from the proxy without an origin, or replace the body of a generated status.Configuration
Weighted traffic split across clusterssupportedroutes[].clustersA route lists clusters with weights; a cookie or header can pin a client to one of them.Configuration
Request mirroringsupportedroutes[].mirrorSends a sampled copy of matching requests to another cluster and discards the answer. Large bodies are skipped.Configuration
Request and response rewritessupportedroutes[].transformsPath prefix, query, and header edits on the way to the origin; response header edits on the way back.Route transforms
Static filessupportedstaticFilesServes a directory, with optional gzip and brotli.Static files

Load balancing ​

CapabilityStatusConfig keyNotesDocs
Balancing algorithmssupportedclusters[].algorithmRoundRobin, Random, LeastRequests, and LeastTime.Configuration
Weights, priority, backup destinations, and slow startsupportedclusters[].destinations[].weight, clusters[].destinations[].priority, clusters[].destinations[].backup, clusters[].slowStartSecondsSlow start ramps a new destination from 10 percent of its weight.Configuration
Session affinity by cookie, header, or hashsupportedclusters[].sessionAffinity, clusters[].hashKeyAn opaque affinity cookie, a sticky header, or consistent hashing on a chosen key.Configuration
Concurrency caps and a wait queuesupportedclusters[].destinations[].maxConcurrentRequests, clusters[].queueThe queue waits briefly when every destination is at its cap.Configuration
Service discoverypartialplus.options: discovery.*Plus watches a file, polls DNS, and queries Consul or Kubernetes EndpointSlices. Consul and Kubernetes discovery are best-effort.Plus

Health checks ​

CapabilityStatusConfig keyNotesDocs
Passive ejectionsupportedclusters[].healthCheck.passiveTreats 502, 503, and 504 as failures by default, caps the share ejected, and sends one trial after reactivateAfterSeconds.Configuration
Active probessupportedclusters[].healthCheck.activeProbes run on a background timer and only restore destinations that a probe marked unhealthy.Configuration
Probe endpoints for orchestratorssupportedserver.admin/healthz and /readyz on a port no proxy listener shares. Readiness turns 503 on SIGTERM before the drain starts.Admin listener
Drain and maintenance statessupportedplus.controlPlaneAn operator drains a destination from the dashboard or the control-plane API (Plus).Plus

Retries and budgets ​

CapabilityStatusConfig keyNotesDocs
Connect failover to the next destinationsupportedroutes[].retry.attempts, clusters[].retry.attemptsIdempotent methods by default.Configuration
Gateway-status replay with backoff and jittersupportedroutes[].retry.statusCodes, routes[].retry.backoffMilliseconds, routes[].retry.jitterPercent, routes[].retry.honorRetryAfterReplays a 502, 503, or 504 onto another destination before anything reaches the client.Configuration
Retry budgetsupportedroutes[].retry.budgetPercent, routes[].retry.budgetMinConcurrentLimits replays in flight to a share of the cluster's in-flight requests. Refused replays are counted.Configuration
Per-try timeoutsupportedroutes[].retry.perTryTimeoutMillisecondsEnds a slow try as a 504 on every try but the last.Configuration
Retry of requests with a bodypartialroutes[].retry.retryNonIdempotent, routes[].retry.maxBufferedBodyBytesOnly a body that was fully buffered is replayed. An HTTP/3 client talking to an HTTP/2 origin is not retried.Protocol support

Timeouts ​

CapabilityStatusConfig keyNotesDocs
Connect, header, idle, and request timeoutssupportedserver.timeouts.connectTimeOutSeconds, server.timeouts.clientHeaderTimeoutSeconds, server.timeouts.responseHeaderTimeoutSeconds, server.timeouts.idleReadTimeoutSeconds, server.timeouts.requestTimeoutSecondsZero turns a timeout off.Server reference
Per-route timeout and buffer overridessupportedroutes[].limits.requestTimeoutSeconds, routes[].limits.idleTimeoutSeconds, routes[].limits.maxBufferedBodyBytesA route overrides the server limits for its own sessions.Limits
Drain on shutdownsupportedserver.admin.preStopDelaySecondsKeeps serving for the delay after /readyz flips, then drains in-flight requests.Kubernetes

Rate limiting ​

CapabilityStatusConfig keyNotesDocs
Request rate limit per keysupportedpolicies[].key, policies[].algorithm, policies[].limit, policies[].windowSeconds, policies[].burstFixed window or token bucket, keyed by client, forwarded client, header, cookie, or route. Answers 429 with Retry-After.Configuration
Concurrent connection capssupportedlisteners[].maxConcurrentClients, server.limits.maxConcurrentClientsAdmission control per listener or for the whole server.Limits
Rate limit shared across instancessupportedpolicies[].scope, policies[].fleetFailMode, policies[].localShare, plus.options: state.mode, plus.options: state.redisLeased fleet token bucket over Redis; the request path stays sync. Default scope node is unchanged.Configuration

Auth methods ​

CapabilityStatusConfig keyNotesDocs
Required header and API key checkssupportedpolicies[].headerName, policies[].headerValueThe requireHeader and apiKey policy kinds refuse a request that lacks the header or value.Configuration
External authorization servicesupportedpolicies[].url, policies[].failOpen, policies[].cacheSecondsAn HTTP service allows or denies each request. Redirects are not followed, and a short positive cache is optional.Configuration
OpenID Connect loginsupportedpolicies[].issuer, policies[].clientIdAuthorization-code flow with PKCE and an encrypted session cookie (Plus).Login policy
JWT, API key, and Basic authenticationsupportedplus.options: security.*JWKS-verified JWT, API keys, and Basic users with bcrypt or PBKDF2 hashes (Plus).Plus
Address allow and deny listssupportedpolicies[].allow, policies[].denyIPv4 and IPv6 addresses and CIDR prefixes.Configuration
Kerberos and NTLM to upstream proxiespartialserver.enableWinAuthSwitch is in the file; credential and proxy-auth callbacks are set in .NET code.Code-only callbacks
Multi-user dashboard accountssupportedplus.controlPlane.dashboardUsersFilePer-person operator and viewer accounts from a local users file (PBKDF2 hashes). Shared secrets remain as optional break-glass.Plus
SSO beyond the OIDC login policysupportedplus.options: controlPlane.dashboardOidc.*Plus dashboard OpenID Connect (authorization code + PKCE), with group and email allow-lists for operator and viewer roles.Plus

mTLS ​

CapabilityStatusConfig keyNotesDocs
Client certificate to the originsupportedclusters[].httpClient.clientCertificatePath, clusters[].httpClient.clientCertificateKeyPath, clusters[].httpClient.clientCertificatePasswordEnvPEM pair or PFX per cluster. The password comes from an environment variable, never the file.Upstream TLS
Private CA, SNI override, and hostname policy for an originsupportedclusters[].httpClient.caBundlePath, clusters[].httpClient.serverName, clusters[].httpClient.verifyHostnameThe bundle replaces the machine trust store for that cluster.Upstream TLS
Client certificates from callerssupportedlisteners[].clientCertificateMode, listeners[].clientCertificateCaPathMode is none, allow, or require, checked against the CA file you name.Features

TLS policy ​

CapabilityStatusConfig keyNotesDocs
Minimum TLS version and OCSP stapling for listenerssupportedserver.tls.minVersion, server.tls.ocspStaplingApplies to the handshake with clients; origin-facing handshakes are not changed.Listener TLS policy
Cipher suite list for listenerspartialserver.tls.cipherSuitesLinux and macOS only. On Windows .NET has no cipher suite policy, the list is ignored, and validation prints a warning.Listener TLS policy
Automatic certificates (ACME)supportedcertificates.acmeDomain, certificates.acmeEmail, certificates.acmeDirectoryObtains certificates from Let's Encrypt or another ACME directory.Certificates and ACME
0-RTT (early data)not supported—System.Net.Quic does not offer early data, so every QUIC connection starts with a full 1-RTT handshake.HTTP/3

Caching ​

CapabilityStatusConfig keyNotesDocs
Shared response cachesupportedplus.options: cache.enable, plus.options: cache.maxBytesIn-memory RFC 9111 subset with Vary, revalidation, size limits, and request collapsing (Plus).Response cache
Cache purgesupportedplus.controlPlaneBy exact key or prefix through the control plane at /v1/cache/purge (Plus).Response cache

Compression ​

CapabilityStatusConfig keyNotesDocs
Response compression (gzip, brotli)partialserver.responseCompression, routes[].compressionBuffered or streaming. Runs on HTTP/1.1 and the HTTP/2-to-HTTP/1.1 bridge only, not on HTTP/2-to-HTTP/2, HTTP/3, or HTTP/1.1-to-HTTP/2.Response compression
Request decompression with size and ratio limitssupportedserver.requestDecompressiongzip and brotli request bodies on HTTP/1.x, with a decompressed-size cap and a zip-bomb ratio limit.Request decompression

WAF ​

CapabilityStatusConfig keyNotesDocs
Signature screening with detect mode and anomaly scoringsupportedpolicies[].mode, policies[].paranoiaLevel, policies[].blockThresholdBuilt-in rule pack, per-route override, and an operator deny-list (Plus).Request screening
Custom rulessupportedplus.options: waf.rulesFileYour own YAML rules next to the built-in pack.Plus
Geo-IP databasesnot supported—Address policies match IP addresses and CIDR prefixes only. No geo-IP data is read.Configuration

Observability ​

CapabilityStatusConfig keyNotesDocs
Prometheus metricssupportedserver.metricsText exposition of the core meter with bounded label sets.Prometheus metrics
Traces and metrics export over OTLPsupportedserver.telemetryW3C trace context through the proxy. The OTEL_* environment variables set the defaults.Telemetry
Access logsupportedserver.accessLog, server.requestIdOpt-in NDJSON written after each response, with sampling. Bodies are never buffered for it.Access log
Read-only dashboardsupportedplus.controlPlane.dashboardPortOverview, routes and clusters, health, config, certificates, and audit views (Plus).Plus
Dashboard route editingnot supported—The dashboard shows routes read-only, with Drain and Healthy buttons. Change routes in the file, or push a snapshot through the control plane.Plus

Kubernetes ​

CapabilityStatusConfig keyNotesDocs
Helm chart for the proxysupporteddeploy/helm/titaniumConfig, probes, a disruption budget, autoscaling, ServiceMonitor, and a sample NetworkPolicy.Kubernetes
Hardened container imagesupportedghcr.io/justcoding121/titanium-web-proxyChiseled base, non-root, read-only root filesystem, linux/amd64 and linux/arm64. It has no libmsquic, so HTTP/3 is off.Kubernetes
ConfigMap and Secret reloadsupportedtitanium run --watchFollows the atomic ..data swap and reloads once. A reload that fails validation keeps the running config.Kubernetes
Gateway API HTTPRoutepartialGatewayClass titaniumHTTP core of the standard channel. A rule the controller cannot honor answers 500 and says why in the route status.Gateway API
Ingresssupportednetworking.k8s.io/v1 IngressServed by the same controller, with titanium.io annotations for rewrites and canary.Ingress
Gateway API TLSRoute, TCPRoute, UDPRoute, and BackendTLSPolicynot supported—The controller does not watch them; only HTTPRoute is served. GRPCRoute is not watched either.Gateway API
Hot binary upgradenot supported—titanium update replaces the executable and the process restarts. Roll pods behind the readiness drain instead.Kubernetes

Protocols ​

CapabilityStatusConfig keyNotesDocs
HTTP/1.1 and HTTP/2supportedserver.enableHttp2, listeners[].enableHttp2HTTP/2 is on by default.Protocol support
HTTP/3 over QUICsupportedserver.enableHttp3, listeners[].enableHttp3On when QUIC is available. The container image has no libmsquic.HTTP/3
Bridging between HTTP versionssupportedserver.originHttpVersionPolicyHTTP/1.1, HTTP/2, and HTTP/3 clients reach origins that speak another version. Not every bridge covers every feature.Protocol support
WebSocket over HTTP/1.1 and HTTP/2supportedserver.enableRfc8441HTTP/1.1 upgrade always; RFC 8441 extended CONNECT when enabled.Protocol support
gRPC-Web to native gRPCsupportedroutes[].grpcWebBinary unary and server-streaming calls to an HTTP/2 origin.gRPC-Web
gRPC and JSON transcodingsupportedplus.options: grpc.transcode.enabledREST and JSON to gRPC through a descriptor set (Plus).gRPC-JSON transcoding
PROXY protocol from a load balancersupportedlisteners[].acceptProxyProtocol, listeners[].trustedProxyProtocolSourcesReads the preamble only from the sources you trust.Configuration
CONNECT-UDP relay (MASQUE)supportedlisteners[].masqueOpt-in listener type. It relays datagrams opaquely, with authentication, tunnel caps, and a private-target block.Listeners
WebSocket over HTTP/3not supported—RFC 9220 extended CONNECT over HTTP/3 is not implemented. WebSocket works over HTTP/1.1 and HTTP/2.Protocol support
Explicit-proxy h2c Upgradenot supported—Upgrade: h2c is not handled. Cleartext HTTP/2 works with prior knowledge only.Protocol support
Decrypting QUIC inside CONNECT-UDPnot supported—The relay forwards each datagram as it came, so the payload stays encrypted end to end. There is no switch to decrypt it.Listeners

L4 ​

CapabilityStatusConfig keyNotesDocs
TCP passthrough with SNI routingsupportedlisteners[].passthrough, listeners[].sniRoutes, listeners[].sniDefaultClusterIdReads the ClientHello, picks a cluster by server name, and forwards the bytes unchanged. Balancing, failover, and an idle timeout apply.TCP passthrough
UDP relaysupportedlisteners[].type, listeners[].maxSessions, listeners[].maxDatagramsPerSecondPerClientOne upstream per client endpoint, with session and rate caps.UDP listeners
PROXY protocol v2 to TCP originssupportedlisteners[].sendProxyProtocol, clusters[].sendProxyProtocolA cluster setting replaces the listener setting. TCP passthrough only.PROXY protocol
SOCKS and transparent listenerssupportedlisteners[].typeExplicit, transparent, SOCKS, QUIC, MASQUE, and UDP listener types.Listeners

Extensibility ​

CapabilityStatusConfig keyNotesDocs
Per-route .NET pluginssupportedplugins[].assembly, plugins[].failMode, plugins[].timeoutMs, routes[].middlewareEach plugin loads into its own collectible context, behind a timeout and an exception wall.Plugins
Embedding the engine in .NETsupportedProxyServer eventsThe same engine with event handlers, synthetic responses, and stream hooks.Library
Programmatic route and cluster swapsupportedPUT /v1/snapshotPlus control-plane call. File reload needs no Plus.Graceful reload
Managed fleet control planesupportedplus.options: manager.url, titanium-managertitanium-manager publishes YAML revisions; Plus agents long-poll, ack or nack, and keep a last-known-good file. Not an xDS client.Manager
xDS control planenot supported—There is no xDS client. Use titanium-manager (or the file, titanium reload, the Plus snapshot call, or the Kubernetes controllers) instead.Manager
Lua scriptingsupportedplugins[].kind, plugins[].file, plugins[].settings, plugins[].bodyMode, routes[].middlewareLua 5.4 in sandboxed states, named in a route middleware list. A file runs the request-headers and buffered request-body phases; every phase runs when a .NET host sets the script pipeline. Needs the lua54 native.Scripting
Lua sandbox, limits, and failure modesupportedplugins[].failMode, plugins[].timeoutMs, plugins[].limits.memoryMb, plugins[].limits.maxInstructions, plugins[].limits.epochDeadlineMs, plugins[].limits.poolSizeNo io, require, load, or bytecode. Memory, instruction, and CPU-time limits hold inside the engine even when the script catches errors. A failed call answers 503, or passes the request with failMode open.Scripting
Lua libraries, shared dictionaries, and JWT verificationsupportedplugins[].settings, plugins[].limits.sharedDataBytesjson, base64, hex, url, crypto, linear-time regex, cidr, uuid, timers, metrics, process-wide shared dictionaries with TTL and eviction, and JWKS-based jwt.verify.Scripting
Lua HTTP callouts with an allow-listsupportedplugins[].calloutHosts, plugins[].limits.calloutConcurrency, plugins[].limits.bufferedBodyByteshttp.call reaches only the hosts you list. No system proxy, redirects, or cookies. Refusals and failures come back as nil and an error.Scripting
Lua L4 stream phasessupportedlisteners[].streamFilterson_connect, on_data, and on_close see raw TCP connections. Name the plugin in listeners[].streamFilters on a passthrough listener, or set StreamFilters from a .NET host.Scripting
Script pipeline and chained scriptssupportedscriptPipelineEvery HTTP phase, upstream choice, and several Lua or Wasm hosts in order. Set scriptPipeline in twp.yaml, or ScriptPipeline from a .NET host. Route middleware still runs the request-headers phase alone.Scripting
WASM proxy-wasm modulessupportedplugins[].kind, plugins[].file, plugins[].vmId, plugins[].settings, plugins[].bodyMode, routes[].middlewareproxy-wasm ABI 0.1.0, 0.2.0, and 0.2.1 on Wasmtime, with the Envoy attribute set and a WASI subset. A module is built and started before it replaces the running one. Needs the wasmtime native.Scripting
WASM memory, fuel, and deadline limitssupportedplugins[].failMode, plugins[].timeoutMs, plugins[].limits.memoryMb, plugins[].limits.fuel, plugins[].limits.epochDeadlineMs, plugins[].limits.poolSizeA VM that traps is discarded and rebuilt off the request path. Signal-based traps are off, so Wasmtime does not fight the .NET runtime.Scripting
WASM HTTP and gRPC callouts with an allow-listsupportedplugins[].calloutHosts, plugins[].limits.calloutConcurrency, plugins[].limits.bufferedBodyBytesproxy_http_call, proxy_grpc_call, and gRPC streams reach only the hosts you list. A request paused on a callout resumes when the guest continues it.Scripting
WASM shared data, queues, ticks, and metricssupportedplugins[].vmId, plugins[].limits.sharedDataBytes, plugins[].limits.queueBytesPlugins with the same vmId and module share VMs, shared data with CAS, and queues. Guest metrics appear as three fixed instruments, so a guest cannot create new ones.Scripting
Scripting natives per platformsupportedtitanium scripting-deps statusLua and Wasmtime natives are pinned per runtime identifier and checked by SHA-256. A computer without one keeps running; only a route that names that script kind fails to load. win-arm64 has none.Scripting
OpenResty, Kong PDK, and APISIX Lua APIsnot supported—There is no ngx API, Kong PDK, APISIX plugin API, LuaJIT, FFI, cosocket, or require. Lua here is the 5.4 language with the libraries on the Scripting page.Scripting

This table is written from website/docs/.capabilities.yml. A unit test checks that each config key exists in twp.schema.json, that each link target exists, and that this page carries every row.

Core, CLI, and website: MIT