> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.clubedge.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js SDK

> Integrate the Clubedge Feature Flags SDK into your Node.js backend — Express, Fastify, or any Node.js server.

The Node.js SDK (`@clubedge/feature-flags-node`) wraps the core `FeatureFlagsClient` for server-side evaluation in any Node.js runtime. It's a thin re-export of `@clubedge/feature-flags-sdk-core` with no framework-specific code — works with Express, Fastify, NestJS controllers, or plain Node.js.

## Requirements

| Component       | Requirement        |
| --------------- | ------------------ |
| Node.js         | 18 LTS or later    |
| Package manager | npm, pnpm, or yarn |

## Installation

```bash theme={null}
pnpm add @clubedge/feature-flags-node
# or
npm install @clubedge/feature-flags-node
# or
yarn add @clubedge/feature-flags-node
```

## Quick start

```typescript theme={null}
import { FeatureFlagsClient, ConsoleLogger } from '@clubedge/feature-flags-node';

const client = new FeatureFlagsClient({
  sdkKey: process.env.FF_SDK_KEY!,
  baseUrl: 'https://flags.clubedge.live',
  pollIntervalMs: 30_000,
  cacheTtlSeconds: 60,
  retries: 3,
  logger: new ConsoleLogger('workspace-api'),
});

async function bootstrap() {
  await client.initialize();
  console.log('Feature flags SDK ready');
}

export { client, bootstrap };
```

## Evaluate in a request handler

```typescript theme={null}
import { client } from './flags-client';

app.get('/dashboard', (req, res) => {
  const enabled = client.isEnabled('new_dashboard', {
    userId: req.user.id,
    tenantId: req.user.tenantId,
    country: req.user.country,
  });

  res.render(enabled ? 'new-dashboard' : 'old-dashboard');
});
```

<Warning>
  The `context` argument (`userId`, `tenantId`, etc.) is **accepted but not used** by the SDK for evaluation. See [SDK evaluation model](/feature-flags/reference/sdk-config#evaluation-methods) for why targeting rules and rollouts are pre-evaluated at config-fetch time with empty context. For per-user evaluation, use [Direct HTTP](/feature-flags/reference/evaluation-api).
</Warning>

## Graceful shutdown

```typescript theme={null}
process.on('SIGTERM', () => {
  client.shutdown();
  process.exit(0);
});

process.on('SIGINT', () => {
  client.shutdown();
  process.exit(0);
});
```

## Full example: Express middleware

```typescript theme={null}
import { FeatureFlagsClient, ConsoleLogger } from '@clubedge/feature-flags-node';

const client = new FeatureFlagsClient({
  sdkKey: process.env.FF_SDK_KEY!,
  baseUrl: 'https://flags.clubedge.live',
  pollIntervalMs: 30_000,
  logger: new ConsoleLogger('express-app'),
});

await client.initialize();

// Middleware to gate feature flags per-request
app.use('/api/*', async (req, res, next) => {
  const userId = req.user?.id;

  if (userId && client.isEnabled('new-api-endpoint', { userId })) {
    req.featureFlags = { newApi: true };
  }
  next();
});
```

## Configuration reference

See [SDK configuration](/feature-flags/reference/sdk-config) for the complete options table, lifecycle methods, event model, and cache behavior.

## Next steps

* [Evaluation API (Direct HTTP)](/feature-flags/reference/evaluation-api) — for per-user targeting when the SDK's pre-evaluation model doesn't meet your needs
* [Evaluation engine](/feature-flags/reference/evaluation-engine) — how flags are resolved
* [Admin API](/feature-flags/reference/admin-api) — managing flags, environments, and rules
