Skip to main content
Version: 5.x

Keepalive and timeouts

Keepalive​

A pair that sees no traffic for SESSION_TIMEOUT_MINUTES (default 120) is removed. Pairing again costs a Kyber exchange, so v5 adds an endpoint that keeps an idle client's pairs alive. v4 had no such endpoint.

POST /api/mte-keepalive
Content-Type: application/json

{"clientId": "<token>", "drop": ["<pairId>", "<pairId>"]}
  • One call refreshes the idle timer of every pair the client holds, however many there are.
  • drop lists pairs the client discarded, and the relay deletes them. It may hold at most MAX_PAIRS_PER_CLIENT ids; more is 490 invalid_request.
  • The answer is {"ok": true, "touched": <count>, "dropped": <count>}.
  • A token older than TOKEN_MAX_AGE_SECONDS is answered 475 invalid_token, and the client authenticates again.
  • When the state store cannot be refreshed, the answer is 503 state_store_unavailable with Retry-After. The client keeps its pairs and retries.
  • Keepalive is rate limited per client and answered 488 rate_limited over the limit. See Limits and scaling.
  • The body counts against MAX_CONTROL_BODY_MIB.

The clients schedule it for you:

ClientKeepalive interval
mte-relay-browser engineOne third of the relay's sessionTimeoutSeconds, clamped to 1 to 10 minutes, unless you set keepAliveIntervalMs. It also pings at once when a hidden browser tab becomes visible again.
Outbound relay client (MAR outbound domains)One third of its SESSION_TIMEOUT_MINUTES, clamped to 1 to 10 minutes.

With the default 120 minute session timeout both clients ping every 10 minutes.

Deadlines​

SettingDefaultWhat it bounds
REQUEST_SECONDS30Silence between request frames, and reading the whole request. Each frame that arrives pushes the deadline out, so a slow upload succeeds as long as it keeps moving.
IDLE_TIMEOUT_SECONDS90Silence between response frames. A streaming response, such as server sent events, fails after this long without a byte from the upstream.
RESPONSE_SECONDS0The whole response. 0 means no bound beyond the idle deadline.
HTTP_CLIENT_TIMEOUT_SECONDS30How long the relay waits for the origin's response headers on inbound domains and pass through routes. On an outbound domain it caps each auth, pair, and keepalive call to the next relay.
SESSION_TIMEOUT_MINUTES120Idle lifetime of a pair and of an outbound relay client.
TOKEN_MAX_AGE_SECONDS86400Client token lifetime, checked at pair and keepalive. At least 60.
DRAIN_SECONDS30Shutdown. How long requests in flight may finish after readiness turns 503. 0 takes the default.

REQUEST_SECONDS, RESPONSE_SECONDS, and IDLE_TIMEOUT_SECONDS have per domain overrides in DOMAIN_MAP: request_seconds, response_seconds, and idle_seconds. Discovery advertises the values that apply to each domain.

The relay also waits at most 10 seconds for a request's headers and closes an idle client keep alive connection after 60 seconds. These are fixed, and SocketX applies the same two timers.

Token refresh​

Tokens are checked for age at pair and keepalive, never on the data path. The outbound relay client refreshes its token at 80 percent of tokenMaxAgeSeconds, while the token is still valid, so it keeps its client id and its pairs. The browser engine refreshes only after the relay answers 475 invalid_token. By then the token has aged, so auth issues a new client id and the engine drops its pairs and pairs again.

Load balancers and proxies​

  • Streamed responses can be quiet for up to IDLE_TIMEOUT_SECONDS between frames. A load balancer or proxy with a shorter idle timeout closes such a stream first, so raise it for routes that stream.
  • The relay closes an idle keep alive connection after 60 seconds, a fixed value. A load balancer that keeps an idle connection to the relay open longer can send a request on a connection the relay has just closed and answer it with its own 502. When one idle timeout covers both streams and idle connections, as on an AWS Application Load Balancer, a value above 60 seconds trades occasional 502 answers for longer quiet streams.
  • Every framed response carries X-Accel-Buffering: no and Cache-Control: no-store, no-transform, private, so proxies that honor them pass frames through without buffering or caching.
  • On SIGTERM a worker turns /readyz to 503 with phase stopping first. Then the relay listener stops accepting, requests in flight drain for up to DRAIN_SECONDS (30 by default), the relay closes its state store, and the probe listener closes last. A managed worker also sends its goodbye to the control plane inside the same budget, so the fleet view drops it at once. Give the orchestrator a termination grace period above DRAIN_SECONDS, or it kills the process before the drain ends. SocketX honors DRAIN_SECONDS with the same sequence.

Connection transports​

PING_INTERVAL_SECONDS, MAX_PAIR_BYTES, and MAX_PAIR_SECONDS are advertised for connection transports, such as WebSocket, that share the protocol. The HTTP relay advertises them and does not act on them. DRAIN_SECONDS is advertised as the drain window on a connection and is also the relay's own shutdown budget. The relay still validates that PING_INTERVAL_SECONDS is below IDLE_TIMEOUT_SECONDS.