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.

Upgrading a 7.x install: Migrating from 7.x to 8.0.

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 (A/AAAA or SRV), 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.activeRequires plus.enabled. Prefer plus.options resilience.activeHealth for the full Plus resilience path; titanium test rejects healthCheck.active without Plus.Plus
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.redisRequires plus.enabled. Leased 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.maxBytesRequires plus.enabled with cache.enable. In-memory RFC 9111 subset with Vary, revalidation, size limits, and request collapsing.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, optional zstd)partialserver.responseCompression, routes[].compressionBuffered or streaming on HTTP/1.1 clients, HTTP/2 clients, and HTTP/3 clients across H1/H2/H3 origin bridges when interception is on. Optional zstd is registered by the CLI when listed in algorithms. Fast-path passthrough stays identity.Response compression
Request decompression with size and ratio limitssupportedserver.requestDecompressiongzip and brotli request bodies on the session path, with a decompressed-size cap and a zip-bomb ratio limit. Extended CONNECT is skipped.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 country allow and denysupportedpolicies[].kind, policies[].allow, policies[].deny, server.geoIpDatabasePathRequires plus.enabled. Country codes from an operator-supplied MaxMind DB. Unknown countries fail closed on allow lists and pass on deny-only lists.Geo route policy

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 editingsupportedplus.controlPlane.dashboardEditing, plus.controlPlane.overlayPath, plus.controlPlane.snapshotValidationOperators add, edit and delete routes and clusters in a JSON editor with Validate, Save and Delete. Edits are validated, applied live, persisted in an overlay and audited; the overlay can be cleared. The snapshot PUT is validated too.Plus
Overload protectionsupportedserver.overload.enabled, server.overload.heapPercent, server.overload.threadPoolQueue, server.overload.activeConnections, server.overload.actionsOff by default. Samples heap, thread-pool queue, and active connections with hysteresis; sheds keep-alives and new requests at elevated/critical. Nearly free when not triggered.Overload protection

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 BackendTLSPolicysupportedTLSRoute, TCPRoute, UDPRoute, BackendTLSPolicy, backendTLSPolicy.enabledOptional informers tolerate a missing CRD. BackendTLSPolicy ConfigMap RBAC is behind backendTLSPolicy.enabled (default false). GRPCRoute is also translated.Gateway API
Hot binary upgradepartialserver.hotRestart.enabled, listeners ReusePortLinux only: SO_REUSEPORT plus a pid-file and SIGUSR2 handover (the new process signals the old one, which closes its TCP listeners, drains and exits); titanium restart starts the successor and waits for the handover. HTTP/3 and UDP listeners cannot be shared, so they bind after the old process exits and are unavailable for that short gap. Prefer rolling pods behind readiness drain.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
WebTransport over HTTP/1.1 and HTTP/2partialserver.enableWebTransport, listeners[].acceptWebTransport, listeners[].webTransportCapsule byte bridge, plus a type: webtransport terminate listener with a pinned HTTP origin. Off by default. HTTP/3 WebTransport is not implemented.Protocol support
connect-tcppartialserver.enableConnectTcp, listeners[].acceptConnectTcpOff by default. Explicit listeners can opt in with server.enableConnectTcp. Any listener can set acceptConnectTcp. HTTP/3 still returns 501.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[].masque, listeners[].acceptConnectUdpOpt-in listener type, or acceptConnectUdp on an existing listener with the same masque policy. Authentication, tunnel caps, and a private-target block still apply.Listeners
WebSocket over HTTP/3supportedserver.enableRfc8441RFC 9220. HTTP/3 clients reach HTTP/1.1, HTTP/2 and HTTP/3 origins.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
TCP TLS termination and originationsupportedlisteners[].terminateTls, listeners[].tlsHandshakeTimeoutSeconds, listeners[].alpn, listeners[].maxConcurrentHandshakes, clusters[].destinations[].useHttpsTerminates inbound TLS on a passthrough listener and relays plaintext, or originates TLS to upstream destinations with useHttps.TCP TLS termination
Zone-aware load balancingsupportedclusters[].zoneAware, clusters[].destinations[].zone, server.localZonePrefers destinations in server.localZone until too few are healthy, then spills to all zones. Off when zoneAware is unset.Zone-aware balancing
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 planesupportedxds.server, xds.node.id, xds.failOpen, server.reloadListenersRequires plus.enabled and a loaded Plus module. Client only; no server. Listeners, routes, clusters, endpoints, and secrets are dynamic via ADS; see the supported-field table.xDS
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 proxy-wasm ABI 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
Listener changes without restartsupportedserver.reloadListenersOff by default for file reload; xDS forces it on. Reconciles listeners with drain and rollback.xDS

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