Skip to main content
FrontMCP supports multi-pod deployments with automatic session failover. When a pod dies, surviving pods detect the failure via Redis heartbeat keys and atomically claim orphaned sessions using a Lua CAS (compare-and-swap) script.

Quick Start

Enable distributed mode with Redis:
Set the deployment mode and build:

Architecture

The HA module has three components that work together:

Heartbeat Service

Each pod writes a heartbeat key to Redis every 10 seconds with a 30-second TTL. When a pod dies, its key expires automatically.
Other pods check for heartbeat presence before attempting session takeover. If a heartbeat key is missing, the owning pod is presumed dead.

Session Takeover

When a request arrives for a session owned by a dead pod, the receiving pod runs an atomic Lua script against Redis:
  1. Read the session data
  2. Verify the current nodeId matches expectedOldNodeId (the dead pod)
  3. Atomically update nodeId to the new pod and set reassignedAt / reassignedFrom
  4. Return success or failure
This CAS operation prevents two pods from claiming the same session simultaneously.

Notification Relay

MCP notifications (progress updates, resource changes) targeting sessions on other pods are relayed via Redis Pub/Sub:
  • Each pod subscribes to mcp:ha:notify:{nodeId}
  • When a notification targets a session on another pod, it is published to that pod’s channel
  • The receiving pod delivers the notification to the local transport

Configuration

Configure HA settings via frontmcp.config.ts:
Set heartbeatTtlMs to at least 2x heartbeatIntervalMs to avoid false positives from network jitter.

Orphan Session Scanner

In addition to on-demand session takeover (when a request arrives for a dead pod’s session), FrontMCP runs a periodic orphan scanner that proactively detects and claims sessions from dead pods:
  1. Runs every heartbeat interval (default: 10s)
  2. Compares all session nodeId values against alive heartbeat keys
  3. Claims orphaned sessions via the same atomic Lua CAS script
  4. Fires a callback for each claimed session (logged at INFO level)
The scanner starts automatically in distributed mode — no configuration needed. The first scan runs after one full heartbeat interval plus the grace period to allow the cluster to stabilize.

Load Balancer Affinity

FrontMCP sets two identifiers on both Streamable HTTP and SSE responses for load balancer routing:
  • Cookie: __frontmcp_node --- set during the initialize handshake
  • Header: X-FrontMCP-Machine-Id --- set on every response in distributed mode

NGINX Sticky Sessions

The affinity cookie ensures subsequent requests from the same MCP client hit the same pod. If the pod dies, the load balancer routes to a different pod, which triggers session takeover.

SSE-Specific Routing

SSE (Server-Sent Events) requires special attention because the /sse endpoint creates a long-lived connection. POST requests to /message must reach the pod with the active SSE stream. FrontMCP handles this in two layers:
  1. LB Affinity (primary): The __frontmcp_node cookie is set during SSE initialization, so the load balancer routes subsequent POST requests to the correct pod.
  2. Notification Relay (fallback): If a POST arrives at the wrong pod, FrontMCP detects that the session exists on another node and relays the message via Redis Pub/Sub to the owning pod, which delivers it through the active SSE stream.
Unlike Streamable HTTP sessions, SSE sessions cannot be recreated on a different pod because the SSE response stream is tied to the original HTTP connection. If the owning pod dies, the client must re-establish the SSE connection on a new pod.
For NGINX, enable sticky sessions via the affinity cookie and ensure long-lived connections are supported:

Kubernetes

Deploy with 3 replicas and a Redis instance:
Each pod gets its machine ID from the Kubernetes HOSTNAME environment variable (set to the pod name automatically). Do not override HOSTNAME in your deployment spec.

Errors

Verifying HA

Transport Security

CORS, bind address, DNS rebinding, and host validation

Health Checks

Configure /healthz and /readyz probes

Redis Setup

Redis connection and session store configuration

Runtime Modes

Standalone, distributed, and serverless modes