Skip to content
Introduction

Regions

One box per region, chosen by where the caller is. There is no cluster.

There is no cluster. A region is one VM running one livekit-server, with its own key pair and its own firewall, sharing nothing with any other region.

Adding a region is standing up a second box and adding a row to configuration. It is never a code change.

Why it is shaped this way#

A region going down should not be able to take another one with it. There is no coordination step to fail, no shared state to diverge, and no clustering software to operate. The cost is that a room lives on exactly one region — a caller in Singapore and a caller in Virginia joining the same room means one of them is crossing an ocean, and there is no mechanism that mends this.

Choosing by caller, not by capacity#

Selection is caller proximity. The VM's only job is moving packets, so the region that minimises distance to the caller is always correct — there is no scenario where routing a Singapore caller to Virginia is right for capacity reasons.

caller_country is an ISO 3166-1 alpha-2 code, taken from the country code of an inbound phone number or from the client's own locale for a web call. Pass it to start_call and list_live_calls.

The country-to-region map is deliberately coarse — good enough for two or three regions, not a geo-IP service. Extend the map before reaching for a routing provider; most of the value is "not obviously wrong", not "optimal".

A caller country that maps to nothing falls back to the first configured region rather than throwing. A misclassified caller on a working region beats a dropped call over a geo-routing edge case.

Configuring them#

REGIONS_JSON is an array of region specs. Key names, never key values — the same rule as env/.env.example, so a region table can be committed and read without carrying a secret:

[
  { "id": "sg",      "label": "Singapore", "url": "wss://sg.example.com",
    "apiKeyEnv": "LK_SG_KEY",   "apiSecretEnv": "LK_SG_SECRET" },
  { "id": "us-east", "label": "Ashburn",   "url": "wss://use.example.com",
    "apiKeyEnv": "LK_USE_KEY",  "apiSecretEnv": "LK_USE_SECRET" }
]

A region whose named key or secret is missing from the environment is dropped from the list, not reported. That is a deliberate fail-quiet: a half-configured region that mints tokens nothing can use is worse than one that is not offered. Check what the control plane actually loaded with describe_call_config rather than by reading the JSON.

One region needs none of this#

With REGIONS_JSON unset, the control plane falls back to the single LIVEKIT_URL / LIVEKIT_API_KEY / LIVEKIT_API_SECRET triple and caller_country is ignored. A one-region deployment never needs to know the region system exists.

Costs, measured#

Region idLocationTypePrice/month
euFalkensteincx23 2c/4GB$5.99
sgSingaporecpx12 1c/2GB$17.99
us-eastAshburncpx11 2c/2GB$20.49

Server types are location-locked and the provider's API misreports it — cx23 exists only in the EU, and cpx11 publishes a Singapore price for a type that is not available there. The runbook at The media plane has the working combinations.

Up nextOverview