MTE Relay questions and answers
The questions below are the ones customers ask most often about MTE Relay v5, grouped by topic. Every answer links to the page that holds the detail. Each question has its own link. Hover a heading and use its anchor link to get the address of that one question.
Product basics
What is MTE Relay?
MTE Relay applies MicroToken Exchange (MTE) protection to HTTP(S) traffic without an application rewrite. An MTE Relay client library, or a second Relay, encrypts each request before it leaves; the Relay in front of your API decrypts it, forwards plain HTTP to the upstream, and encrypts the response for the trip back. Your API sees ordinary HTTP. MTE Relay ships as two packages built on the same core: MTE Relay Server for client to server traffic and MTE API Relay for server to server traffic. The introduction describes the MTE technology behind both.
What is the difference between MTE Relay Server and MTE API Relay?
MTE Relay Server (MRS) protects traffic from web and mobile applications. The client side is an SDK inside the application, and the Relay runs in front of the backend. MTE API Relay (MAR) protects traffic between two services with a chain of two Relays: an outbound Relay next to the calling service takes ordinary HTTP and encrypts it, and an inbound Relay in front of the destination API decrypts it. Neither service changes beyond the address it calls. Both packages run the same Relay program with the same settings. They differ in the MTE library build each image links. An MRS pairs only with the client SDKs, and a MAR pairs only with another MAR. See MRS and MAR images.
Does MTE Relay replace TLS?
No. Run both. TLS protects the connection between two hops. MTE protects the application data itself, from the SDK to the Relay, so a CDN, load balancer or WAF that terminates TLS in the middle sees only ciphertext in the body and in the encrypted metadata. The Relay listens on plain HTTP and expects a TLS terminator in front of it. The client token, the pairing exchange and the frame envelopes travel in the clear inside the HTTP exchange, which is why every hop belongs inside TLS. See WAF, CDN, and proxy notes.
What traffic can MTE Relay protect?
HTTP and HTTPS request and response exchanges: REST and JSON APIs, form posts, file uploads and downloads, and streamed responses such as server sent events. Every HTTP method works, and the path, query, headers and body travel encrypted, apart from the few values listed under Which parts of a request are encrypted. WebSocket traffic is the job of SocketX, a separate product built on the same frame format, and a TCP gateway for raw connections such as SSH or database protocols is built on that frame too, with its availability announced separately. gRPC, which needs HTTP/2 streams and trailers end to end, is outside what the HTTP Relay carries. The engineering guide describes the three transports.
Do I need to change my backend?
No. The Relay forwards each decrypted request to the upstream named in
DOMAIN_MAP as ordinary HTTP, with the original method, path, query, headers
and body, plus the standard X-Forwarded-Host, X-Forwarded-Proto and
X-Forwarded-For headers. Cookies, authorization headers and status codes pass
through. The backend facing choices are optional: pass_through_routes for
paths that should skip encryption, preserve_host when the API needs the
client's hostname, and per domain headers the Relay adds on the way in. See
DOMAIN_MAP.
Do I need to change my client applications?
For MTE Relay Server, one small change per application: swap fetch for
mteFetch in a web app, add one provider in Angular, or route requests through
the SDK on iOS, Android and Flutter. The SDK handles authentication, pairing,
encryption, keepalive and recovery. MTE API Relay needs no SDK. The calling
service points its HTTP client at the outbound Relay instead of the remote API,
and the Relay chain does the rest. See the client libraries under
MTE Relay Server and
outbound domains.
Security
What encryption does MTE Relay use?
MicroToken Exchange. MTE protects your data in transit with values from NIST SP 800-90A deterministic random bit generators, so the same message looks different every time, and only the paired endpoint can recover the original. Two encode types exist: standard MTE, which replaces your data with random tokens that are not derived from it, and MKE (Managed Key Encryption), the default, which encrypts with a cipher keyed from those generators and is the efficient form for bodies of any size. Each pair is established with a CRYSTALS Kyber key exchange, 1024 by default. See the introduction and What is new in v5.
How is MTE Relay quantum resistant?
The key exchange that establishes each pair is CRYSTALS Kyber, a lattice based
key encapsulation designed to resist attack by a quantum computer, at the 1024
parameter set by default. 512 and 768 are available through KYBER_STRENGTH,
but the browser engine always uses 1024, so keep the default on any Relay that
serves browsers; v4 used 512. The keys and tokens MTE uses come from random bit generators seeded through
that exchange. Both ends check the
Kyber strength and the library profile before pairing, so a mismatch fails at
setup with a clear message. See Kyber strength
and the v5 brief.
Is MTE Relay FIPS validated or NIST approved?
MTE's random bit generators are the NIST SP 800-90A CTR DRBG and Hash DRBG algorithms, and pairing uses the CRYSTALS Kyber key encapsulation. For questions about formal validation, compliance statements and the exact algorithm set in your build, contact Eclypses Support.
Which parts of a request are encrypted?
The method, path, query string, headers and body of every request, and the
status, headers and body of every response, travel inside encrypted frames. A
few values ride in the clear by design: a one byte method code for the nine
standard methods and the response status, both of which the receiver checks
against the encrypted copy; the browser's cookies and the origin's
Set-Cookie, because a browser applies Set-Cookie only from a real HTTP
response (forward_browser_cookies, on by default); headers you list in the SDK's
unencryptedHeaders; and anything on a pass through route. The Relay's own
X-MTE-Relay-* headers carry routing and error information, never application
data. See What is new in v5.
Is data verified before it reaches my application?
Yes. Every request, response and nonempty data frame is one complete MTE or
MKE operation, and neither end releases a byte of plaintext until the frame is
verified. A corrupted or forged frame produces no plaintext. Corrupt request
data never reaches your API, and corrupt response data never reaches the
client. The encrypted method, frame version and frame flags must also match
their plaintext copies, or the Relay refuses the request with
483 header_mismatch and logs a security event, and the client refuses a
response whose status disagrees with its encrypted copy. The v4 streaming path released
decrypted chunks before its final integrity check; v5 does not. See
Why v5.
How does MTE Relay handle replayed requests?
Each frame advances the MTE state of its pair, so a request captured and sent
again does not decode. The Relay answers 479 replay_rejected, keeps the pair
usable, and logs a security event. The same property means a proxy or load
balancer must never retry an encrypted request on its own; the SDKs send a
failed request again by themselves only where nothing ran at the origin. See
Errors and recovery.
Does the Relay store or log my data?
No request or response data is written to disk. Pair state lives in memory, or
in Redis when replicas share it, and the control plane stores configuration,
not traffic. The audit event for each encrypted request records hashes and
sizes, never plaintext, and a secret that appears in a log line shows three characters
followed by asterisks. At LOG_LEVEL=debug the operational log carries decoded
request paths, so keep production at info. Codec state saved in Redis is not
encrypted at rest, so restrict who can reach the store. See
Event schema.
How are clients authenticated, and does this replace my application's authentication?
Every client holds a signed token: a client id, an issue time and an HMAC
SHA256 under the domain's client_id_secret. The token rides in every request,
its signature is checked on the data path, and its age (24 hours by default) is
checked at pairing and keepalive. Pairing itself is a Kyber exchange, and the
auth, pair and keepalive endpoints are rate limited. This proves that a request
came from a paired client; it does not identify your users. Your own
authentication, whether Authorization headers, cookies or session tokens,
travels inside the encrypted frames to the origin unchanged. See
Pairing, tokens, and abuse limits.
Does MTE Relay protect against denial of service, or replace a WAF?
It is neither a WAF nor a DDoS shield, and it runs behind yours. What it has:
rate limits on the auth, pairing and keepalive endpoints (600 auth and 600
pairing calls per minute per source, 60 pairing and 120 keepalive calls per
minute per client), a configurable request body cap, hard
bounds on frames and metadata that are checked before any memory is allocated,
and a token check that needs no store lookup. The data path is never rate
limited. A WAF in front of the Relay still filters by source address, rate and
Host, but every encrypted request reaches it as POST / with a ciphertext
body, so exclude the encrypted route from body rules and allow
application/octet-stream. See
Rate limits and
CORS and WAF.
How is the container image hardened?
The runtime image is Google's distroless cc-debian12 base with the Relay
binary and its runtime libraries, and no shell, package manager or OS
utilities. The binary is compiled in a separate build stage, so build tooling
and source never ship. The container runs as the unprivileged nonroot user,
declares only ports 8080 and 9091, and runs on OpenShift under the default
restricted-v2 constraint without changes. No secrets are baked in beyond the
development license. See
Security.
Are the images scanned for vulnerabilities?
Yes, before release, and scan reports for the current tag are available from Eclypses Support on request. Because you pull the image into your own registry, you can also produce your own evidence with Amazon ECR enhanced scanning, Microsoft Defender for Containers, Oracle's vulnerability scanning service, or a scanner such as Trivy or Grype. See Vulnerability scanning.
How quickly are security fixes released?
Critical vulnerabilities are addressed in a patched image within 30 days of confirmed disclosure, and lower severities in a subsequent release. Patches ship out of band rather than on a calendar. Applying one means pulling the new tag and redeploying; within v5, releases are additive and need no client changes. See Maintenance.
Which secrets do I manage, and where do they live?
The MTE license (COMPANY_NAME and LICENSE_KEY), one client_id_secret per
DOMAIN_MAP host, REDIS_URL when it carries a password, and, with the control
plane, CONTROL_PLANE_TOKEN, ADMIN_PW and ADMIN_JWT_SECRET. A standalone
Relay reads them from its environment, so your orchestrator's secret store
supplies them. A managed fleet enters the license, the client secrets and
REDIS_URL once in the control plane, which keeps them on its own volume and
shows the values workers run as fingerprints. CONTROL_PLANE_TOKEN and
ADMIN_PW stay in the environment, and ADMIN_JWT_SECRET only seeds the
session signing secret, which the control plane then keeps on its volume. The
control plane API carries these secrets, so keep it on an internal network
behind TLS. See Environment variables
and Control plane security.
Latency and overhead
How much latency does MTE Relay add?
About one millisecond per request at light load for the full round trip through
two Relays, encrypting and decrypting in both directions, against a fraction of
a millisecond straight to the origin. The cost is a small, roughly fixed amount
per request, not a multiplier on network distance. In a June 2026 test across
the public internet, with one Relay on a residential connection and the other
on AWS in us-east-1, the Relay pair added a median of 2.07 ms to a 56 ms
round trip, about 3.7 percent. That run was v4; v5 has not been measured across
a WAN yet. With two Relay replicas sharing Redis, v5 answers 39% faster than
v4 at light load, 1.13 ms against 1.86 ms. See
MTE Relay performance.
How much bandwidth does the encryption add?
Little on large bodies, and a flat amount on small ones: below 1 KiB the Relay adds about 1,880 bytes per round trip. Ciphertext travels as raw bytes in the body, never as Base64 text in a URL or header. With MKE, the default, each frame costs a 12 byte envelope plus the fixed overhead of one MKE operation, and the first frame of a request adds 64 bytes of fixed fields, the token and pair id among them. Standard MTE encodes each plaintext byte as 8 bytes, which is why MKE is the default. On the loopback bench a 1 GiB download carried 0.028 percent of wire overhead, a 1 KiB request round trip moved 4,261 bytes, and on a 1 MiB body the 64 KiB default frames cost 7,445 more bytes per round trip than 1 MiB frames, 0.36 percent. Pairing is the one larger exchange, about 15 KB for authentication, discovery and the Kyber exchange together, and it happens when a client starts, not per request. See Measurements.
What does the first request cost?
The first request from a client to a Relay origin authenticates, reads the discovery document and pairs, which includes the Kyber exchange, about 10 ms and 15 KB on the loopback bench, once when a client starts. The browser SDK waits for one pair and fills the rest of its pool in the background, and keepalive calls, every 10 minutes by default, keep pairs alive while a client is idle, so a returning client does not pair again; a pair with neither traffic nor keepalive expires after 120 minutes. Outbound Relays in a MAR chain hold a warm pool of pairs for the same reason. See Keepalive and timeouts.
Does Kyber 1024 slow anything down?
Not on the data path. The key exchange runs only at pairing, and a 4 CPU Relay measured the same throughput with Kyber 1024 as with 512: 9,190 against 9,152 requests per second. The stronger parameter set is paid at pairing, which happens once per pair, not per request. See Kyber strength.
Will my users notice anything?
Not in normal use. The added latency is about a millisecond, the first request
on a page pays one pairing, and the SDK keeps pairs alive while the page stays
open and pings as soon as a hidden tab becomes visible again. Requests look
different in the browser's network tab, as POST / with
Content-Type: application/octet-stream in place of the original method and
path. When something fails, the SDK raises a typed error with a code, a reason and a recommended
action, and the request id in it matches the Relay's log line. See the
JavaScript client.
Does it support streaming and large files?
Yes. Bodies move as frames of at most MAX_FRAME_BYTES, 64 KiB by default, so
memory follows the frame size rather than the body size: a 1 GiB upload ran
through a Relay at 277 MiB/s with a 44 MiB peak RSS on the loopback bench. The
exception is an outbound Relay in an MTE API Relay chain, which buffers each
request body before framing it, so set MAX_REQUEST_BODY_MIB there. The Relay
sends the response status and headers as soon as the origin answers, before
the first body byte, so server sent events and other streamed responses start
at once, and a streamed response may stay quiet for up to
IDLE_TIMEOUT_SECONDS (90 by default) between frames. The request body cap is
unlimited by default, and the mobile SDKs stream file uploads and downloads
with progress callbacks. See Streaming.
Capacity and sizing
How many requests per second can one Relay handle?
Measured on 5.0.0 with 10 KB JSON requests and a pair of Relays in one cluster: about 2,760 requests per second at 1 CPU, 5,200 at 2 CPU, 9,150 at 4 CPU and 13,570 at 8 CPU, where the test rig itself was the limit. A 4 CPU / 4 GB Relay pair moves about 790 million encrypted requests a day, and across the 131 million requests of the run not one failed. Throughput is 37% higher than v4 on the same 2 CPU Relay. See MTE Relay performance.
How much CPU and memory does a Relay need?
CPU is the limiter and memory is small. At 10 KB payloads a Relay stayed under 160 MiB on every shape measured (86 to 152 MiB), with 42 to 91 MiB at 2 KB and 250 to 411 MiB at 100 KB. Memory tracks payload size, not load, and did not grow under overload. v4 needed about 2 GB per Relay at 10 KB, so v5 uses about 90% less. Size by CPU; the 1 to 8 GB memory limits used in the runs left ample headroom. See Resource footprint.
What happens when a Relay is overloaded?
Requests queue. Throughput holds flat at the Relay's ceiling, latency rises in proportion to the excess demand, and nothing fails: at eight times saturating demand 99 percent of requests still completed in under 34 ms, at sixteen times the error count stayed at zero, and a separate run at 1,000 connections held 8,337 requests per second without an error. Overload shows up as queueing delay, not as error storms, so alert on latency. See Measured throughput and latency.
Does payload size change capacity?
Yes, but less than you might expect. The measured cost per request is about
141 µs of Relay pair capacity plus 4.8 µs per KB, so at 10 KB three quarters of
the cost is independent of the payload. Plan capacity by request rate for small
payload APIs, and note that moving the same data in larger requests costs less
than in many small ones: 10 KB requests cost about four times less capacity per
byte than 2 KB requests. To estimate the ceiling for any payload size, take
1 ÷ (141 µs + 4.8 µs × KB) and scale by the CPU curve. See
Payload size sensitivity.
How do I size a deployment?
Take your peak sustained request rate, adjust it for payload size, and pick the smallest tier whose recommended load covers it, running at or below 60 percent of measured saturation so p99 latency stays low. The tiers at 10 KB: Small, one 2 CPU Relay with no shared state, up to 3,100 requests per second; Medium, two 2 CPU Relays with one Redis, up to 4,900 and highly available; Large, two 4 CPU Relays with one Redis, up to 7,800; Enterprise, independent cells of the Large tier that scale linearly. Confirm a size beyond the measured range with a one hour certification sweep before relying on it. See Deployment tiers.
Deployment and runtimes
How is MTE Relay delivered?
As container images: one for MTE Relay Server and one for MTE API Relay, built
for linux/amd64, distroless, and tagged per release. Customers pull them from
Eclypses' private registry with credentials Eclypses issues and copy them into
their own registry (Amazon ECR, Azure Container Registry, OCIR, Artifact
Registry, the OpenShift internal registry, or any private registry), which is
also the recommended production setup because registry authorization tokens
expire. The web SDK is an npm package; the mobile SDKs come from Maven Central
for Android, Swift Package Manager or CocoaPods for iOS, and GitHub for the
Flutter plugin. See
On premises deployment.
Where can I run it?
Anywhere that runs a linux/amd64 container. The documentation has guides for
Docker, Docker Compose, Kubernetes, OpenShift and Docker Swarm on premises;
Amazon ECS and EKS; Azure Kubernetes Service; Google Kubernetes Engine; and
Oracle Cloud Container Instances and OKE. Podman, K3s and other runtimes run the
same image. The control plane runs on the same runtimes and knows the restart
commands for Kubernetes, OpenShift, Swarm, Compose, ECS and systemd. See the
deployment cards under MTE Relay Server and
MTE API Relay.
What does a deployment depend on?
A single Relay on the on premises image depends on nothing but its upstream.
Pair state stays in memory,
and DOMAIN_MAP is the only required setting. Two or more replicas that serve
the same clients need a Redis instance for shared pair state and the same
client_id_secret on every replica. Production also needs a TLS terminator in
front of the Relay, because the Relay serves plain HTTP. The control plane is
optional. See
Running more than one replica.
Can it run in an air gapped network?
Yes, with the on premises image. The Relay makes no calls to Eclypses at
runtime. The license is checked locally from COMPANY_NAME and LICENSE_KEY,
and the on premises images carry no marketplace metering. Its only network
dependencies are the upstream, Redis when you share state, and the control
plane when you run one. The exception is an image built for the AWS
Marketplace, which registers with AWS Marketplace metering at startup and stops
when it cannot, so an air gapped network runs the on premises image. Mirror the
image into a registry inside the network and deploy from there. See
Pull the Docker image.
Does it support HTTP/2 and HTTP/3?
Clients can use HTTP/2 or HTTP/3 to your TLS terminator. The Relay itself serves
HTTP/1.1 on its plain listener, so the terminator speaks HTTP/1.1 to the Relay,
which load balancers and ingress controllers do by default. Toward an https://
upstream the Relay negotiates HTTP/2 when the origin offers it. See
HTTP mapping.
Where should the Relay sit in my network?
Inside your protected network, directly in front of the API it protects, behind the load balancer or ingress that terminates TLS. For MTE API Relay, run each Relay next to the service it fronts, the outbound Relay beside the caller and the inbound Relay beside the API, so the plaintext hops never leave the host or the cluster network. Keep the probe port and the control plane off public networks; they are for the orchestrator and the operators. See Load balancers and proxies.
Which ports does it use?
Two by default: 8080 for traffic (LISTEN_PORT) and 9091 for the liveness and
readiness probes (PROBE_PORT, which 0 disables). A control plane instance
listens on its own LISTEN_PORT, 8081 in the documented examples, and the Go
profiler port 6060 opens only while ENABLE_PPROF is on. Outbound, the Relay
reaches its upstream, Redis and the control plane at the addresses you
configure. See Environment variables.
How is it configured?
Through environment variables, with DOMAIN_MAP as the one required setting: a
JSON map from each hostname clients call to its upstream and per host options.
Every other setting has a documented default and validation rule. A boolean,
integer or level name that fails to parse logs a warning and uses the default,
while a value that would make the Relay unsafe, such as an invalid DOMAIN_MAP
or port, stops it at startup with the reason. With the control plane, a setting
resolves in the order control plane override, then environment variable, then
default, and six settings apply live without a restart. See
Environment variables and
DOMAIN_MAP.
What is the control plane, and do I need it?
It is optional. The control plane is the same image started with MODE=control:
a web admin panel and JSON API where you enter the license and hosts once, and
every worker that polls it picks the configuration up. It adds a setup wizard,
live edits to DOMAIN_MAP and five other settings, a fleet view of every worker
and what it is running, a 50 version history with diff and rollback, scoped
service tokens for automation, and an audit line in its log for every write.
Workers keep serving their
last applied configuration if the control plane goes away. A single Relay or a
small fleet configured from environment variables works without it. See
Control plane.
Can one Relay serve several APIs or hostnames?
Yes. DOMAIN_MAP keys can be hostnames, host:port, *.example.com wildcards
or a catch all *, and each entry carries its own upstream, client secret,
CORS policy, pass through routes, headers and timers. The Relay picks the entry
from the request's Host header, most specific first, so one fleet can front
many services or many tenants. See DOMAIN_MAP keys.
Does it work behind my load balancer, CDN or WAF?
Yes, with a few rules for the device in front: allow application/octet-stream
request bodies, do not buffer or transform responses, do not retry encrypted
requests, keep the X-MTE-Relay-Error response header, and give routes that
stream an idle timeout above IDLE_TIMEOUT_SECONDS, 90 by default. Where one
idle timeout also covers idle connections, as on an AWS Application Load
Balancer, a value above 60 seconds trades occasional 502 answers for longer
quiet streams, because the Relay closes an idle connection after 60 seconds.
Relay errors use statuses 470 to 490, a block that CDNs pass through unchanged
where they would replace a 5xx or 403 body with their own page, and that
service mesh outlier detection does not count against the pod. Behind a proxy,
set
TRUSTED_PROXIES so each client gets its own rate limit budget, and hash on
X-MTE-Relay-Route when you want each client pinned to one replica. See
WAF, CDN, and proxy notes.
How do health checks work?
A probe listener on port 9091 answers GET /healthz for liveness and
GET /readyz for readiness, and readiness turns 503 while a worker waits for
configuration or drains at shutdown. For a load balancer or a security scanner
that can only reach the traffic port, HEALTH_CHECK_PATH mounts a health
answer at a path you choose, for any Host and outside every rate limit, and
GET /api/mte-echo answers as it did in v4. The image is distroless, so a
Docker Compose or ECS health check command cannot run inside the container;
check from outside. See
Health checks and scanners.
How do I run it highly available?
Run two or more replicas behind a load balancer with the same client_id_secret
on every replica and REDIS_URL pointing at one Redis without cluster mode, so
any replica can serve any client and a replica can be replaced without breaking
sessions. Only the inbound side needs shared state; outbound Relays keep their
pairs in process, so a highly available chain runs one Redis where v4 needed
two. Add replicas for availability and size each one for throughput, because
one 4 CPU Relay moved more than two 2 CPU Relays sharing Redis. Sticky routing
on X-MTE-Relay-Route with LOCAL_STATE_CACHE saves a Redis round trip per
state read. See
Running more than one replica.
What happens if Redis or the control plane goes down?
Redis is a hard dependency, so run it with the availability the fleet needs.
While it is unreachable, requests that need pair state fail with retryable
errors
(503 state_store_unavailable at pairing and keepalive, 470 pair_not_found
on the data path) until it returns, and clients pair again afterwards; there is
nothing to restore, because pair state is short lived. While the control plane
is down, workers keep serving their last applied configuration and catch up on
their next poll, and a worker that cannot validate a new document keeps the old
one. See How the control plane works
and Errors and recovery.
How do restarts and upgrades affect users?
A Relay drains on SIGTERM: readiness turns 503, the listener stops
accepting, requests in flight finish within DRAIN_SECONDS (30 by default),
and only then does the process exit. The listener closes as soon as readiness
turns 503, so a load balancer that has not yet seen the 503 can still send
a new request to a stopping Relay; keep more than one replica for a rolling
update, and give the orchestrator a termination grace period above the drain
budget. Without Redis, a restart loses pair state and
clients pair again on their next request. The browser SDK does that itself
after a 475 invalid_client_id, though the request that found the Relay
restarted is surfaced to your code as a repaired error, and your code decides
whether to send it again. With Redis, sessions survive. An upgrade within v5 is
a redeploy with the new tag, with no client change. See
Fault recovery.
Client platforms
Which client platforms are supported?
Web applications through mte-relay-browser-public-client, a fetch
replacement, and mte-relay-angular, an HttpClient transport for Angular 17
through 22; iOS through a Swift package; Android through a Maven library that
works with Volley and OkHttp; and Flutter through a plugin for iOS and Android.
Each needs its frame version 2 release, and any frame version 2 client works
with any v5 Relay. MTE API Relay needs no client library. See Version compatibility.
How does the browser integration work?
Install the npm package and replace fetch with mteFetch for calls to the
Relay origin. The package bundles the MTE WebAssembly engine and the license and
initializes itself on import, so there is no setup call. On the first request
to a Relay origin it authenticates, reads the Relay's discovery document, checks
that the Relay speaks frame version 2 with a matching library profile and Kyber
strength, and pairs. After that it encrypts each request, decrypts each
response, keeps a small pool of pairs, sends keepalives and recovers from Relay
errors. Angular gets the same engine through one provider, and existing
interceptors keep seeing plaintext. See the
JavaScript client and
the Angular client.
Will browsers send a CORS preflight for every request?
For cross origin calls, yes, because application/octet-stream is not a CORS
safelisted content type. The Relay answers preflights itself with 204 from the
domain's CORS settings, and cors_max_age_seconds lets browsers cache the
answer so most requests skip the preflight. When you customize
cors_allowed_headers, keep Content-Type and X-MTE-Relay-Route in the
list. See CORS for browser clients.
Do cookies, sessions and my existing authentication keep working?
Yes. Authorization headers and every other application header travel inside
the encrypted frame and reach your API unchanged. Browser cookies ride the
plain HTTP request, and the origin's Set-Cookie moves to the plain HTTP
response, the only response a browser applies Set-Cookie from, so cookie
sessions work, subject to the browser's third party cookie rules when the Relay
host is on a different site from the application. The cookie must be valid for the Relay host, because the Relay does not
rewrite Domain or Path. The browser SDK sends credentials by default, and
the Relay allows them unless a domain turns cors_allow_credentials off. See
Cookies.
What happens when a request fails?
The SDK throws a typed error carrying the Relay code, a reason token, the registered recovery action, the Relay's message and the request id. It repairs or replaces pairs on its own as the action says, sends a request again by itself only in the two cases where nothing ran at the origin, and otherwise leaves the retry decision to your code, which knows whether the request was idempotent. An answer that is not a valid frame, such as a CDN error page or a WAF block, is a transport error and never application data. On an outbound domain the calling service receives errors as JSON bodies with the same code and reason. See Errors and recovery.
How do mobile apps move to a new Relay version?
Within v5, servers and clients need not move together, because any frame version 2 client works with any v5 Relay release, so an app on an older v5 SDK keeps working after a Relay upgrade. The v4 to v5 move is different, because the wire protocols differ. A mobile app keeps using the SDK it shipped with until users update, so run the old and new Relay versions side by side on different hostnames, ship the app build that points at the new one, and retire the old Relay when its traffic stops. See the cutover plan.
Operations
How do I monitor MTE Relay?
Through its structured JSON logs. Every request produces a performance event,
and each encrypted request that reaches the origin adds its decrypt, validate,
proxy and encrypt timings; security events cover token failures, replays and
header mismatches; an audit record holds hashes only; and error events report
faults. The events of one request share a correlation id that is also the
X-MTE-Relay-Request-Id the client sees and the Relay sends upstream. No vendor agent runs inside the Relay. Your log shipper forwards the
container output, and this site provides a Datadog pipeline, dashboard and
monitors, a New Relic dashboard and alert policy, and Grafana dashboards for
CloudWatch Logs Insights and Loki. See
Monitoring and integrations.
What do the 470 to 490 status codes mean?
They are Relay faults, each with a reason token and a registered client action:
a missing or failed pair (470 to 474), a bad token (475), a malformed frame,
an oversized frame or body, or bad metadata (477, 481, 482), an unsupported
protocol version (478), a
replay (479), a Host with no DOMAIN_MAP entry (480), a bound envelope
mismatch (483), outbound capacity (485), rate limiting (488) and validation
failures (490). The Relay keeps 500, 502 and 503 for true server, upstream and
state store faults. The code travels twice, in an ERROR frame body and in the
X-MTE-Relay-Error header, so it survives a proxy that replaces the body. A
relayed response always travels as HTTP 200; the origin's real status is inside
the frame. See Errors and recovery.
How much does the Relay log, and can I reduce it?
Per request performance events dominate the volume, and the Relay emits them
for every request. Filter or sample those in your log shipper or log platform
when cost matters, and keep security, error and audit events unsampled. Echo
hits are logged at debug, and probe and health check path hits are not logged,
so a load balancer check does not fill the log. LOG_LEVEL=warn still carries
medium, high and critical security events. See Log volume.
Versions and support
Can v4 clients talk to a v5 Relay?
No. v5 uses a new binary wire protocol, frame version 2, and there is no dual
stack mode. A v5 Relay serves only v5 clients, and a v4 Relay serves only v4
clients. A v4 client that reaches a v5 Relay gets 478 frame_version_unsupported
on its first call and never gets a session, and the Relay logs the minimum SDK
versions at warn level. Servers and clients therefore
upgrade together, per application, and the documented cutover plan runs v4 and
v5 side by side on different hostnames until every application has moved. See
Upgrading from v4.
Do clients and servers have to upgrade together within v5?
No. Within a major version, releases are additive and backwards compatible, and any frame version 2 client works with any v5 Relay release. Upgrading a server is a redeploy with the new tag and no client change, and a feature added in a later minor is marked in the documentation with a Since badge naming the minimum server version. See Version compatibility.
How often are releases, and how long is a version supported?
Images are published as needed, when features, dependency updates or fixes warrant a release, with security patches out of band. Breaking changes arrive only with a new major version, which gets its own documentation set. MTE Relay v4 is supported until October 1, 2027, its images stay available at least until then, and its documentation stays online. See the v4 support policy.
How is MTE Relay licensed?
MTE Relay is a commercially licensed and commercially supported product. A
license is a company name and key, set on every Relay through COMPANY_NAME
and LICENSE_KEY. The images ship with a development license so that an
evaluation runs out of the box, and production deployments set their own. On
the AWS Marketplace images the subscription is the license, so both stay unset.
The public web client package bundles its license, and the Angular client takes the
license in its provider. Contact
Eclypses for terms.
Is there a trial build?
There is no v5 trial build yet. The MTE Relay Server trial build runs v4, and v4 components cannot pair with v5. For a v5 evaluation, the release images run with their built in development license, so the server side of an evaluation needs only access to the images. See the trial build page and contact Eclypses.
How do I get support?
Licensed and subscribed customers contact Eclypses Support at
customer_support@eclypses.com, Monday
to Friday, 8:00 AM to 5:00 PM MST, excluding holidays, for
escalations, scan reports and hardening documentation. Include the
X-MTE-Relay-Request-Id of a failing request where you have one; it ties the
client error to the Relay and origin logs. See
Support.