Skip to content

Core Concepts

Flags

A feature flag is the central object in Sidekick. Every flag has:

FieldTypeDescription
keystringUnique identifier (e.g. new-checkout-flow)
is_enabledbooleanMaster on/off switch
rollout_percentagenumber | null0–100 percentage rollout, or null for 100%
descriptionstring | nullHuman-readable description
rulesTargetingRule[]Optional targeting rules

Flag Key Naming

Use lowercase kebab-case for flag keys: new-checkout-flow, beta-dashboard, dark-mode-v2. Keys are immutable after creation — to rename a flag, delete and recreate it.

Targeting Rules

Targeting rules let you enable a flag for specific users regardless of the rollout percentage.

A rule has three parts:

FieldTypeDescription
attributestringUser attribute to match (e.g. email, plan)
operatorOperatorHow to compare the attribute
valuesstring[]List of values to match against

Operators

OperatorDescriptionExample
equalsExact match (any value in the list)plan equals ["enterprise"]
not_equalsNo match in the listplan not_equals ["free"]
containsSubstring matchemail contains ["@acme.com"]
starts_withPrefix matchregion starts_with ["eu-"]
ends_withSuffix matchemail ends_with ["@contractor.com"]

Rule Evaluation

  • Rules are evaluated in order; first match wins
  • If a rule matches, the flag returns true immediately (bypasses rollout %)
  • If no rule matches, evaluation falls through to the rollout percentage

Example: Internal Beta

Enable a flag for all employees regardless of the 5% global rollout:

json
{
  "key": "ai-assistant",
  "is_enabled": true,
  "rollout_percentage": 5,
  "rules": [
    {
      "attribute": "email",
      "operator": "ends_with",
      "values": ["@yourcompany.com"]
    }
  ]
}

Result:

  • alice@yourcompany.comtrue (rule match)
  • bob@customer.com → 5% chance of true (rollout hash)

Rollout Percentage

The rollout percentage enables gradual feature releases. Sidekick uses deterministic consistent hashing (MurmurHash3) to assign users to buckets:

  • The same user always gets the same result for the same flag
  • Buckets are stable across restarts and server instances
  • Increasing from 10% to 20% enables the flag for a new cohort without disrupting the existing 10%

Special Values

  • null (no rollout) — effectively 100%; all users get true if enabled
  • 0 — no one gets true (useful to disable without deleting)
  • 100 — everyone gets true

User Context

When evaluating a flag, you provide a user context:

typescript
client.isEnabled('flag-key', 'user-id', {
  email: 'alice@example.com',
  plan: 'pro',
  region: 'eu-west-1',
})
  • user-id — the stable identifier used for rollout hashing (typically your database user ID or UUID)
  • Attributes — arbitrary key-value pairs used for targeting rule matching

Attributes are never sent to the server — they are only used locally for rule evaluation.

SSE Stream

The SSE stream (GET /stream) is the connection between the server and each SDK client. It uses the W3C Server-Sent Events standard.

Events

EventPayloadDescription
connected"true"Connection established; SDK resets its store
updateJSON stringA flag was upserted or deleted
(keep-alive)keep-alive-textHeartbeat every 15 seconds

Update Payload

json
// Upsert
{"type": "UPSERT", "flag": { ...flag object... }}

// Delete
{"type": "DELETE", "key": "flag-key"}

Authentication

Set SDK_KEY on the server to require authentication. All requests to /api/* and /stream must include:

Authorization: Bearer <SDK_KEY>

Without SDK_KEY, the server runs in open mode (suitable for local development only).

Released under the MIT License.