Skip to content

Quickstart

Use Gates through OpenFeature — the CNCF-standard feature-flag API. Register the Lucerna provider once, then every read goes through the vendor-neutral @openfeature/server-sdk, so your application code never imports a Lucerna SDK directly.

Every evaluation is one round trip to the Gates server-side engine: no background poller, no exposure queue, nothing to close. That makes the provider a natural fit for serverless and edge handlers.

1. Get your server key

In the dashboard, open Settings → API keys and copy the server key (ck_srv_…). It carries the gates:evaluate grant the provider needs, and it picks the environment: production key, production rules. The publishable ck_client_… key is refused at startup.

2. Install

bash
pnpm add @lucerna-dev/gates-openfeature @lucerna-dev/gates-node @openfeature/server-sdk
bash
npm install @lucerna-dev/gates-openfeature @lucerna-dev/gates-node @openfeature/server-sdk
bash
bun add @lucerna-dev/gates-openfeature @lucerna-dev/gates-node @openfeature/server-sdk

@lucerna-dev/gates-node and @openfeature/server-sdk are peer dependencies of the provider.

3. Register the provider

Once, at startup:

ts
import { OpenFeature } from "@openfeature/server-sdk";
import { LucernaProvider } from "@lucerna-dev/gates-openfeature";

await OpenFeature.setProviderAndWait(
  new LucernaProvider({
    serverKey: process.env.LUCERNA_SERVER_KEY!,
    onError: (error) => console.error("[gates]", error.message),
  }),
);

Wire onError: reads never throw, so without it a misconfigured key serves safe defaults ("everything off") silently.

4. Read flags and experiments

ts
const client = OpenFeature.getClient();

// targetingKey becomes the Gates userId; other attributes become traits.
const context = { targetingKey: user.id, plan: user.plan };

// Feature flag → true / false
if (await client.getBooleanValue("new_billing", false, context)) {
  // show the new billing page
}

// Experiment → variant name, or your default when the user isn't in it
const variant = await client.getStringValue("checkout_test", "control", context);

Boolean reads answer flags (kill switches folded in — a thrown switch reads false). String reads answer experiment variants, and the exposure is recorded server-side on the same request. Gates has no number or object flags, so those reads answer your default with TYPE_MISMATCH.

That's it. Next: the reference, using the provider in NestJS, or Vercel's Flags SDK.

Lucerna Developer Docs