Offline Mode (Air-Gapped)
Some environments block all outbound internet traffic — regulated enclaves, government clouds, disconnected networks. Offline mode lets those deployments keep using feature flags with no changes to application code: your services talk to a small in-cluster relay instead of the hosted FlagTGL control plane, and that relay serves flags from a local file you manage from the command line.
Switching between hosted and offline is only the value of one SDK setting —
relayProxyUrl. Nothing else in your application changes.
| Mode | relayProxyUrl |
|---|---|
| Hosted | https://flagtgl.com (or your FlagTGL host) |
| Offline | http://flag-file-relay.<namespace>.svc.cluster.local:8080 |
Offline mode is free and intentionally lightweight — it covers flag delivery, not the hosted control plane. Runtime targeting, guarded rollouts, approvals, and evaluation analytics remain part of FlagTGL.
How it works
Every FlagTGL and LaunchDarkly server SDK supports a relay proxy URL. Point it at
flag-file-relay — a small container that implements the same relay endpoints
(GET /all streaming, GET /sdk/latest-all polling, POST /bulk events) and
reads flags from a YAML file. The SDK cannot tell the difference between the relay
and the hosted service.
your service ──(relayProxyUrl)──▶ flag-file-relay ──▶ flags.yaml (ConfigMap)
(SDK, unchanged) (in-cluster) (you edit this)
1. Install the relay
The image is public and self-contained:
docker pull docker.io/anchoo2kewl/flag-file-relay:v0.1.0
Install with Helm when a registry is reachable:
helm install ffr ./chart -n <namespace>
Fully air-gapped install
On a machine with internet access, build a self-contained bundle and copy it in:
./offline/bundle.sh # produces flag-file-relay-offline.tgz
scp flag-file-relay-offline.tgz user@host:
On a host with cluster access:
tar xzf flag-file-relay-offline.tgz && cd flag-file-relay-offline
./install.sh --registry <your-private-registry>
The bundle contains the image, manifests, and installer, so nothing is ever pulled from the internet at run time.
2. Manage flags from the command line
Flags live in a ConfigMap and are edited with the flagctl helper — there is no
separate UI to run offline:
flagctl list # all flags and values
flagctl get new-rbac # one flag
flagctl set new-rbac true # global default
flagctl set new-rbac true --tenant acme.example.com # per-tenant override
Changes hot-reload within about a minute — no restart and no SDK reconnect.
File format
flags:
new-rbac:
value: false # default when no override matches
tenants: # optional per-tenant overrides
prod.acme.com: true
new-alerts: false # shorthand: a bare value is the default
max-report-schedules:
value: 15 # numbers and strings are supported
| Field | Meaning |
|---|---|
value | Default returned when no override matches. |
tenants | Map of tenant key to value, matched against the SDK's tenant context. |
users | Map of user key to value, matched against the SDK's user context. |
3. Point your services at the relay
Set the relay proxy URL to the in-cluster service. For the FlagTGL and LaunchDarkly server SDKs this is a single field:
launchDarklyClient:
sdkKey: offline # any value; the relay is in-cluster
relayProxyUrl: http://flag-file-relay.blues.svc.cluster.local:8080
To return to hosted mode later, set relayProxyUrl back to your FlagTGL host and
roll the services. No code change is required.
Verify
A correctly wired service loads its flags on startup and logs a successful data-source event, with no initialization errors. You can also query the relay directly:
kubectl -n <namespace> exec deploy/flag-file-relay -- flag-file-relay list
kubectl -n <namespace> exec deploy/flag-file-relay -- wget -qO- http://localhost:8080/sdk/latest-all
Capabilities
| Capability | Offline |
|---|---|
| Boolean, string, and number flags | Yes |
| Per-tenant and per-user overrides | Yes |
| Hot reload without restart | Yes |
| Percentage rollouts, complex rules, segments | Edit the file directly |
| Runtime evaluation analytics and context insights | Hosted FlagTGL |
When connectivity returns, switch relayProxyUrl back and your existing SDK setup
resumes streaming from FlagTGL with full analytics — no migration required.