---
title: "Relay Parameters (Railway + Vercel)"
description: "This document covers all environment variables used by the AIS/OpenSky relay path."
---
This document covers all environment variables used by the AIS/OpenSky relay path:

- Railway relay process: `scripts/ais-relay.cjs`
- Vercel relay proxy endpoints (legacy): `api/opensky.js`, `api/ais-snapshot.js`, `api/polymarket.js`, `api/rss-proxy.js`

<Note>
  The `api/*.js` edge function endpoints listed above are legacy patterns being phased out in favor of the sebuf proto-first approach. See [Adding Endpoints](/adding-endpoints) for the current recommended pattern.
</Note>
- Server relay callers: `server/worldmonitor/*` handlers
- Optional browser local fallback callers in `src/services/*`

## 1) Minimum Production Setup

Set these before enabling strict relay auth.

### Railway (relay)

| Variable | Required | Example | Notes |
| --- | --- | --- | --- |
| `AISSTREAM_API_KEY` | Yes | `ais_...` | Required for AIS upstream WebSocket feed. |
| `RELAY_SHARED_SECRET` | Yes | `wm_relay_prod_...` | Must exactly match Vercel value. |
| `RELAY_AUTH_HEADER` | Recommended | `x-relay-key` | Must match Vercel if changed from default. |

### Vercel (proxy + server functions)

| Variable | Required | Example | Notes |
| --- | --- | --- | --- |
| `WS_RELAY_URL` | Yes | `https://<railway-app>.up.railway.app` | HTTPS relay base URL used by server-side proxy calls. |
| `RELAY_SHARED_SECRET` | Yes | `wm_relay_prod_...` | Must exactly match Railway value. |
| `RELAY_AUTH_HEADER` | Recommended | `x-relay-key` | Header name used to forward relay secret. |

## 2) Full Parameter Reference

## Core Relay/Auth

| Variable | Set On | Default | Required | Purpose |
| --- | --- | --- | --- | --- |
| `AISSTREAM_API_KEY` | Railway | none | Yes | Auth for AIS upstream stream source. |
| `VITE_AISSTREAM_API_KEY` | Local dev only | none | No | Local fallback if `AISSTREAM_API_KEY` is missing. Not recommended for production. |
| `PORT` | Railway/local | `3004` | No | HTTP server listen port for relay process. |
| `WS_RELAY_URL` | Vercel + server handlers | none | Yes (for relay-backed features) | Base URL used by Vercel/server to reach Railway relay. |
| `VITE_WS_RELAY_URL` | Browser (local dev) | none | No | Localhost fallback path for direct browser calls in development only. |
| `RELAY_SHARED_SECRET` | Railway + Vercel + self-hosted | empty | **Yes (always)** | Shared secret for non-public relay routes. The relay refuses to start without it unless `I_UNDERSTAND_THIS_DISABLES_AUTH=true`. |
| `RELAY_AUTH_HEADER` | Railway + Vercel | `x-relay-key` | No (but recommended explicit) | Header name carrying relay secret. |
| `I_UNDERSTAND_THIS_DISABLES_AUTH` | Railway / self-hosted | `false` | No | Dev-only escape hatch. If `true`, the relay boots WITHOUT a shared secret, logs a loud `[SECURITY]` line at boot and every 5 minutes, and accepts every request on non-public routes. Never set in production. |
| `ALLOW_UNAUTHENTICATED_RELAY` | Railway / self-hosted | `false` | No | **Deprecated** alias of `I_UNDERSTAND_THIS_DISABLES_AUTH`. Still accepted for back-compat; the relay logs a `[DEPRECATED]` warning when this name is used. |
| `ALLOW_VERCEL_PREVIEW_ORIGINS` | Railway | `false` | No | If `true`, allows `*.vercel.app` origins in relay CORS checks. |

## Relay-Adjacent Feature Flags

| Variable | Set On | Default | Required | Purpose |
| --- | --- | --- | --- | --- |
| `VITE_ENABLE_AIS` | Browser/client build env | enabled (unless `false`) | No | Client-side feature gate for AIS UI/polling. |
| `LOCAL_API_MODE` | Local/server runtime | none | No | If contains `sidecar`, some server handlers bypass relay and call OpenSky directly. |
| `WINGBITS_API_KEY` | Vercel/server | none | No | Military enrichment/fallback source used by server handlers; not required for relay core. |

## OpenSky Upstream Auth

| Variable | Set On | Default | Required | Purpose |
| --- | --- | --- | --- | --- |
| `OPENSKY_CLIENT_ID` | Railway | none | No (recommended) | OAuth client ID for higher OpenSky reliability/rate limits. |
| `OPENSKY_CLIENT_SECRET` | Railway | none | No (recommended) | OAuth client secret paired with client ID. |

## OpenSky Cache/Cardinality Controls

| Variable | Set On | Default | Required | Purpose |
| --- | --- | --- | --- | --- |
| `OPENSKY_CACHE_MAX_ENTRIES` | Railway | `128` | No | Max positive cache keys retained in memory. |
| `OPENSKY_NEGATIVE_CACHE_MAX_ENTRIES` | Railway | `256` | No | Max negative cache keys (`429/5xx`) retained in memory. |
| `OPENSKY_BBOX_QUANT_STEP` | Railway | `0.01` | No | Coordinate quantization step for bbox cache key reuse. `0` disables quantization. |

## AIS Pipeline Tuning

| Variable | Set On | Default | Required | Purpose |
| --- | --- | --- | --- | --- |
| `AIS_SNAPSHOT_INTERVAL_MS` | Railway | `5000` (min `2000`) | No | Interval for rebuilding snapshot payloads. |
| `AIS_UPSTREAM_QUEUE_HIGH_WATER` | Railway | `4000` (min `500`) | No | Pause upstream socket when queue reaches this. |
| `AIS_UPSTREAM_QUEUE_LOW_WATER` | Railway | `1000` (clamped below HIGH_WATER) | No | Resume upstream socket when queue drops below this. |
| `AIS_UPSTREAM_QUEUE_HARD_CAP` | Railway | `8000` (must be `> HIGH_WATER`) | No | Max queue size before dropping incoming upstream messages. |
| `AIS_UPSTREAM_DRAIN_BATCH` | Railway | `250` (min `1`) | No | Max messages drained per cycle. |
| `AIS_UPSTREAM_DRAIN_BUDGET_MS` | Railway | `20` (min `2`) | No | Max CPU time budget per drain cycle. |

## Rate Limit / Logging / Metrics

| Variable | Set On | Default | Required | Purpose |
| --- | --- | --- | --- | --- |
| `RELAY_RATE_LIMIT_WINDOW_MS` | Railway | `60000` | No | Global rate-limit window. |
| `RELAY_RATE_LIMIT_MAX` | Railway | `1200` | No | Default max requests per IP per window. |
| `RELAY_OPENSKY_RATE_LIMIT_MAX` | Railway | `600` | No | OpenSky route max requests per IP per window. |
| `RELAY_RSS_RATE_LIMIT_MAX` | Railway | `300` | No | RSS route max requests per IP per window. |
| `RELAY_LOG_THROTTLE_MS` | Railway | `10000` | No | Minimum interval between repeated log events per key. |
| `RELAY_METRICS_WINDOW_SECONDS` | Railway | `60` (min `10`) | No | Rolling window used by `/metrics`. |

## Platform-Managed Variables (Do Not Manually Set)

These are used only for production detection and are usually injected by platform/runtime.

| Variable | Who sets it | Purpose |
| --- | --- | --- |
| `NODE_ENV` | Runtime/platform | Used to detect production mode. |
| `RAILWAY_ENVIRONMENT` | Railway | Used to detect production relay environment. |
| `RAILWAY_PROJECT_ID` | Railway | Used to detect production relay environment. |
| `RAILWAY_STATIC_URL` | Railway | Used to detect production relay environment. |

## 3) Recommended Starting Values (High Traffic Baseline)

These are safe starting points for a busy relay:

```bash
# Auth + routing — RELAY_SHARED_SECRET is REQUIRED (the relay exits at startup
# without it unless I_UNDERSTAND_THIS_DISABLES_AUTH=true is set).
RELAY_SHARED_SECRET=<strong-random-secret>   # openssl rand -hex 32
RELAY_AUTH_HEADER=x-relay-key
WS_RELAY_URL=https://<your-railway-relay>.up.railway.app
# I_UNDERSTAND_THIS_DISABLES_AUTH=false   # dev-only override; do NOT set in prod

# OpenSky cache/cardinality
OPENSKY_CACHE_MAX_ENTRIES=256
OPENSKY_NEGATIVE_CACHE_MAX_ENTRIES=512
OPENSKY_BBOX_QUANT_STEP=0.01

# AIS pipeline
AIS_SNAPSHOT_INTERVAL_MS=3000
AIS_UPSTREAM_QUEUE_HIGH_WATER=5000
AIS_UPSTREAM_QUEUE_LOW_WATER=1500
AIS_UPSTREAM_QUEUE_HARD_CAP=10000
AIS_UPSTREAM_DRAIN_BATCH=300
AIS_UPSTREAM_DRAIN_BUDGET_MS=20

# Rate limits + metrics
RELAY_RATE_LIMIT_WINDOW_MS=60000
RELAY_RATE_LIMIT_MAX=1200
RELAY_OPENSKY_RATE_LIMIT_MAX=600
RELAY_RSS_RATE_LIMIT_MAX=300
RELAY_LOG_THROTTLE_MS=10000
RELAY_METRICS_WINDOW_SECONDS=60
```

## 4) How to Verify Configuration

Health:

```bash
curl -sS https://<relay>/health
```

Metrics (requires relay auth):

```bash
curl -sS https://<relay>/metrics \
  -H "x-relay-key: $RELAY_SHARED_SECRET"
```

or:

```bash
curl -sS https://<relay>/metrics \
  -H "Authorization: Bearer $RELAY_SHARED_SECRET"
```

Expected checks:

- `auth.enabled` is `true` in `/health` (canonical operator-visible flag — `true` only when a shared secret is configured AND the `I_UNDERSTAND_THIS_DISABLES_AUTH` bypass is NOT engaged). `auth.sharedSecretEnabled` is preserved for back-compat.
- `/metrics.opensky.hitRatio` is stable and high under load.
- `/metrics.ais.dropsPerSec` stays at `0` in normal operation.
- `/metrics.ais.queueMax` is comfortably below `AIS_UPSTREAM_QUEUE_HARD_CAP`.
