All docs
Feature flagsAdd flags to your appcode

Add flags to your app

Read flags on your server and in the browser, bootstrap the first paint, and update live.

What you'll have

Flags read on both sides, with a dashboard toggle reaching an open page in about a second.

You'll need
  • An API key from API Keys
  • A client-side ID from Settings → Project

Pick the SDK for where your code runs, and know what the two sides are for.

Most integrations use two: one on the server, one in the browser. They do different jobs, and doing both is what gives you a correct first paint and a flag that changes on an open page.

Which SDK

Where your code runsSDKCredential
Node server@varia-bly/nodeAPI key
Browser@varia-bly/reactClient-side ID
Python servervariably-sdkAPI key
Go servergithub.com/varia-bly/go-sdkAPI key
Anything elsePlain HTTPEither

The credential column is the part to get right. An API key reaches every variA/Bly feature, so it stays on your server. A client-side ID reaches flag evaluation only and is safe in a bundle. See Introduction to feature flags for the full comparison.

Why both sides

The server resolves flags while the page is being generated, so the HTML is already correct. On its own that is enough — but the value is then fixed until the page renders again.

The browser evaluates on mount and holds a socket open, so a flag toggled in the dashboard reaches a page that is already open, in about a second, with nobody reloading anything.

Together, the server's values seed the browser's provider, so the first render is right and stays right. That seeding is called bootstrapping, and skipping it is what makes a flag-dependent component flash the wrong branch while values load.

// Server: resolve and pass down.
const snapshot = await client.allFlags({ key: '' });

return { props: { bootstrappedFlags: snapshot.values() } };
// Browser: seed the provider with them.
<VariablyProvider clientSideId={...} flags={bootstrappedFlags}>{children}</VariablyProvider>

The context field is named differently per SDK

Same idea, three spellings. It is the identity rules and user overrides match on, so pass something stable per user.

SDKContext
@varia-bly/node, @varia-bly/react{ key: 'user-123' }
variably-sdk (Python){"user_id": "user-123"}
Govariably.UserContext{UserID: "user-123"}

It is not your API key and not a gate key, which is worth saying because { key: ... } reads like either.

Environment variables

VariableWhereValue
VARIABLY_API_KEYserver onlyFrom API Keys
VARIABLY_BASE_URLserverYour API endpoint
NEXT_PUBLIC_VARIABLY_CLIENT_IDbrowser bundleFrom Settings → Project
NEXT_PUBLIC_VARIABLY_BASE_URLbrowser bundleYour API endpoint

Keep the API key out of anything prefixed for the browser. The client-side ID is the credential designed to be published.

A missing flag is an error, not a default

Every SDK raises rather than returning the default you passed when a gate key does not exist. Call validateFlags at start-up with the keys your code reads, and every missing one is reported at once — before a request path reaches whichever is read first.

If a flag reads as undefined in the browser but works on the server

The browser sees only gates available to client-side SDKs. Open the gate and check that Hide from client-side SDKs is unticked.