Overview

The @flagsync/nest-sdk integrates into Nest.js applications for server-side feature management and event tracking—ideal for backend services and APIs.

Installation

Install the SDK with your preferred package manager:

npm install @flagsync/nestjs-sdk

Quickstart

A basic example of using the SDK in a Nest.js application—set up the SDK in two steps:

1

Configure the Module

Import FlagSyncModule in your app.module.ts:

app.module.ts
import { Module } from '@nestjs/common';

import { FlagSyncModule } from '@flagsync/nestjs-sdk';


@Module({

  imports: [

    FlagSyncModule.forRoot({

      sdkKey: 'your-sdk-key',

      // other configuration options

    }),

  ],

})

export class AppModule {}
2

Inject the Client

Use @InjectFlagSync() to inject the client into a Provider (e.g., service, controller, etc.):

app.controller.ts
import { Controller, Get } from '@nestjs/common';

import { FsClient, InjectFlagSync } from '@flagsync/nestjs-sdk';

import { UserContext } from '@app/context.decorator';


@Controller()

export class AppController {

  constructor(@InjectFlagSync() private client: FsClient) {}


  @Get()

  async getMyFlag(@UserContext() context) {

    return this.client.flag(context, 'my-flag');

  }

}

Initialization

The SDK leverages the onModuleDestroy lifecycle event to automatically destroy the FsClient on application shutdown, releasing connections to FlagSync’s servers.

To ensure proper cleanup, call enableShutdownHooks during application startup. See the Nest.js documentation for Application Shutdown

Get Your SDK Key

Find your server-side SDK key in your workspace settings. Keep server-side keys private to protect flag rules.

Initialize the SDK

Initialize the SDK in your Nest.js application using one of these methods:

Synchronous Configuration

Configure the SDK synchronously with forRoot:

import { Module } from '@nestjs/common';

import { FlagSyncModule } from '@flagsync/nestjs-sdk';


@Module({

  imports: [

    FlagSyncModule.forRoot({

      sdkKey: 'your-sdk-key',

    }),

  ],

  ...

})

export class AppModule {}

Asynchronous Configuration

Configure the SDK asynchronously with forRootAsync, ideal for dynamic configuration with ConfigService:

import { Module } from '@nestjs/common';

import { ConfigModule, ConfigService } from '@nestjs/config';

import { FlagSyncModule } from '@flagsync/nestjs-sdk';


@Module({

  imports: [

    ConfigModule.forRoot({

      cache: true,

      isGlobal: true,

    }),

    FlagSyncModule.forRootAsync({

      inject: [ConfigService],

      useFactory: async (configService: ConfigService) => {

        return {

          sdkKey: configService.get('FLAGSYNC_SDK_KEY'),

        };

      },

    }),

  ],

  ...

})

export class AppModule {}

Wait for Readiness

The SDK initializes automatically during module setup—no need to manually wait for readiness with the injected FsClient.

User Context Decorator

Simplify user context access by creating a custom decorator that returns an FsUserContext object. Pass this object to flag() and track() functions.

This enables passing @UserContext() as a parameter in controller methods.

Refer to the Nest.js documentation for Authentication to learn about AuthGuards, which can append user incoming requests.

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

import { FsUserContext } from '@flagsync/nestjs-sdk';


export const UserContext = createParamDecorator(

  (_, ctx: ExecutionContext): FsUserContext => {

    const request = ctx.switchToHttp().getRequest();


    // Populated via middleware or an AuthGuard

    // Or use request.cookies, etc.

    const user = request.user;


    return {

      key: user.userId,

      attributes: {

        jobTitle: user.role,

        region: request.headers['x-region'] ?? 'Unknown',

      },

    };

  },

);

Ensure the key in FsUserContext is unique and persistent for accurate MAU tracking and consistent flag evaluations. See User Context Best Practices for details.

Usage

Evaluate Flags

Evaluate flags with flag(), which applies targeting rules, rollouts, and defaults for the user context.

An Impression is automatically registered when flag() is called.

app.service.ts
import { Injectable } from '@nestjs/common';

import { InjectFlagSync, FsClient, FsUserContext } from '@flagsync/nestjs-sdk';


@Injectable()

export class AppService {

  constructor(

    @InjectFlagSync()

    private readonly client: FsClient,

  ) {}


  async doWork(context: FsUserContext) {

    const isEnabled = this.client.flag(context, 'feature-enabled', false);

    if (isEnabled) {

      // Feature is enabled

    }

  }

}

Track Events

Submit user actions with the track function:

See Events: Tracking to learn about numeric and property events.

checkout.service.ts
import { Injectable } from '@nestjs/common';

import { InjectFlagSync, FsClient, FsUserContext } from '@flagsync/nestjs-sdk';

import { PurchaseRequest } from '@app/types';


@Injectable()

export class CheckoutService {

  constructor(

    @InjectFlagSync()

    private readonly client: FsClient,

  ) {}


  async handlePurchase(request: PurchaseRequest, context: FsUserContext) {

    // Property event

    this.client.track(context, 'purchase-request', null, request);


    // Time the operation

    const t0 = Date.now();

    const order = await this.makePurchase(request);

    const receipt = await this.sendOrder(order)

    const t1 = Date.now()


    // Numeric event

    this.client.track(context, 'purchase-duration', t1 - t0);

  }

}

SDK Event Listeners

The SDK emits these events for SDK lifecycle management:

  • SDK_UPDATE: Emitted when flags are updated
  • SDK_READY: Emitted when the SDK is ready
  • ERROR: Emitted when an error occurs during initialization
import { FsEvent } from '@flagsync/js-sdk';


// Flag updates

this.client.on(FsEvent.SDK_UPDATE, () => {

  this.logger.log(`Flags updated at ${new Date().toISOString()}`)

});

SDK_UPDATE does not fire if syncing is disabled.

Configuration

Configure the SDK with the FsConfig interface:

export interface FsConfig {

  sdkKey: string;

  sync?: {

    type?: 'stream' | 'poll' | 'off'; // Optional: Sync strategy

    pollRate?: number;                // Optional: Polling interval in seconds

  };

  tracking?: {

    impressions?: {

      maxQueueSize: number;           // Required: Max impressions queue size

      pushRate: number;               // Required: Impressions push rate

    };

    events?: {

      maxQueueSize: number;           // Required: Max events queue size

      pushRate: number;               // Required: Events push rate

    };

  };

  urls?: {

    sdk?: string;                     // Optional: SDK endpoint URL

  };

  logger?: Partial<ILogger>;          // Optional: Custom logger

  logLevel?: LogLevel;                // Optional: Logging level

  metadata?: Record<string, any>;     // Optional: Additional metadata

}

Custom Attributes

const context: FsUserContext = {

  key: 'user-123',

  attributes: {

    plan: 'premium',

    country: 'US',

    userType: 'enterprise'

  }

}

Ensure the key in FsUserContext is unique and persistent for accurate MAU tracking and consistent flag evaluations. See User Context Best Practices for details.

Flag Syncing

Configure flag update strategies with the sync object: stream, poll, or off.

By default, flag updates propagate in milliseconds via server-side events (SSE), ensuring the latest values are used in evaluations.

1

Stream (Default)

Stream updates via SSE—flag updates are reevaluated on the server and sent to the client:

FlagSyncModule.forRoot({

  sdkKey: 'your-sdk-key',

  sync: {

    type: 'stream' // Default

  }

});
2

Polling

Poll the server on an interval:

FlagSyncModule.forRoot({

  sdkKey: 'your-sdk-key',

  sync: {

    type: 'poll',

    pollRate: 60

  }

});
3

Off

Disable syncing:

FlagSyncModule.forRoot({

  sdkKey: 'your-sdk-key',

  sync: {

    type: 'off'

  }

});

Bootstrapping

Initialize the SDK with a set of bootstrap flags:

FlagSyncModule.forRoot({

  sdkKey: 'your-sdk-key',

  bootstrap: {

    'my-feature': true,

    'other-feature': false,

  },

});

Best Practices

  • Select a sync strategy (stream/poll/off) based on your application’s needs.
  • Create a User Context Decorator for simplified context management.
  • Add user attributes for targeted feature rollouts.

Environment Variables

Set the following environment variable:

  • FLAGSYNC_SDK_KEY: Your server-side FlagSync SDK key (required)