Ctrl K
ComunidadGuías…

docs/relay-parameters.mdx

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
---
title: "Relay Parameters (Railway + Vercel)"
description: "Every environment variable used by the AIS and OpenSky relay path — Railway + Vercel deployment envs, timeouts, and upstream credential wiring."
---
This document covers all environment variables used by the AIS/OpenSky relay path:

- Railway relay process: `scripts/ais-relay.cjs`
- Desktop-product-only OpenSky relay: `api/opensky.js` (not part of the public API offering)
- Vercel relay proxy endpoints (legacy): `api/ais-snapshot.js`, `api/polymarket.js`, `api/rss-proxy.js`

<Note>
  The legacy proxy endpoints in the second bullet are being phased out in favor of the sebuf proto-first approach. The OpenSky route is a restricted desktop-product transport, not a public integration surface. 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. |
| `RELAY_BIND_HOST` | Local | all interfaces | No | Address the relay listens on. Native installs outside Docker set `127.0.0.1`; leave unset on Railway. |
| `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 and logs a loud `[SECURITY]` line at boot and every 5 minutes. `/status` and `/wits` still require a configured secret. 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. |

## WITS tariff transport

The bilateral tariff handler uses `WS_RELAY_URL`, `RELAY_SHARED_SECRET`, and
`RELAY_AUTH_HEADER` to fetch WITS through the authenticated `GET /wits` route.
Without `WS_RELAY_URL`, it calls WITS directly. A configured relay failure remains
an upstream failure; the handler does not retry through the direct path.

The route accepts one `path` query parameter for TRN reported rows, MFN AVE rows,
reporter/year availability, or country/group metadata. It constructs a fixed
`https://wits.worldbank.org` destination, rejects redirects, and never forwards the
relay secret upstream. Requests have a nine-second deadline through body completion
and a 4 MiB response limit. Upstream status codes and XML pass through unchanged.
The relay sends `no-store`; the tariff handler retains its existing Redis cache,
historical year, source attribution, and tariff basis.

Deploy the relay route before the API caller when activating this transport.
The caller does not fall back to direct WITS if the relay returns 404 because its
route has not been deployed.

## 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. |
| `AIS_RECONNECT_BASE_MS` | Railway | `5000` (min `50`) | No | Base delay of the exponential upstream reconnect ladder. |
| `AIS_RECONNECT_MAX_MS` | Railway | `300000` (min `100`) | No | Ordinary ceiling for the reconnect ladder. |
| `AIS_THROTTLE_RECONNECT_MAX_MS` | Railway | `1800000` (min `100`, and never below `AIS_RECONNECT_MAX_MS`) | No | Escalated ceiling applied once the provider throttles persistently. Clamped up to `AIS_RECONNECT_MAX_MS` when configured lower, so escalation can never shorten the wait and reconnect harder while being throttled. |
| `AIS_THROTTLE_ESCALATE_AFTER` | Railway | `5` (min `1`) | No | Consecutive HTTP 429 upgrade rejections before the escalated ceiling applies. |

## 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`.