NodeJS SDK
FeatureBoard SDK for NodeJS.

Installation

npm add --save @featureboard/node-sdk
# Or
yarn add @featureboard/node-sdk
# Or
pnpm add @featureboard/node-sdk

Usage

Usage of the NodeJS SDK is broken up into two parts:
  1. 1.
    Connect to the FeatureBoard service
  2. 2.
    Get a client SDK based on an audience set, this would normally happen at the beginning of an HTTP request in your node app
This setup is so FeatureBoard does not impact response times of your application, and can calculate the feature values for that user based on their audiences on the fly in memory.

Setup

import { FeatureBoardService } from '@featureboard/node-sdk'
const connection = await FeatureBoardService.init('<your environment key', {})
Fetch
FeatureBoard relies on fetch, if your application uses a particular implementation, you can pass it to the init method. Otherwise, the default implementation will look for a global fetch function, if that is not found then will try to use the node-fetch package.

Getting Feature Values

// First get the client SDK for the current request
const client = connection.request(['audience', 'list'])
// Then use the client in your application to get the current feature value.
// NOTE: You must specify a fallback value, this is used when the feature is unavailable in this environment
const featureValue = client.getFeatureValue('my-feature-key', fallbackValue)

Update Strategies

Because everyone is different FeatureBoard SDKs are designed to work with different update strategies.
Polling is the default update strategy
Manual
Updates to feature values are controlled by your application.
const connection = await FeatureBoardService.init('<your environment key>', {
updateStrategy: 'manual',
})
await connection.updateFeatures()
On Request
This mode is useful for serverless applications where the VM gets paused between invocations, it will guarantee that the feature values are always up to date for the current invocation.
const connection = await FeatureBoardService.init('<your environment key', {
updateStrategy: 'on-request',
})
// NOTE request function must be awaited when using the on-request strategy
await connection.request(['user', 'audiences'])
By default the on-request strategy has a max age cache of 30 seconds, if you want to reduce that you can do so by passing a updateStrategy configuration object. This means the SDK will only check if the feature values have changed after the max age has passed since the last update.
const connection = await FeatureBoardService.init('<your environment key', {
updateStrategy: {
kind: 'on-request',
maxAgeMs: 1000, // 1 second
},
})
// NOTE request function must be awaited when using the on-request strategy
await connection.request(['audience', 'list'])
Polling
Polls the FeatureBoard service for updates every intervalMs milliseconds (default 30 seconds).
const connection = await FeatureBoardService.init('<your environment key', {
updateStrategy: 'polling',
})
// or
const connection = await FeatureBoardService.init('<your environment key', {
updateStrategy: {
kind: 'polling',
intervalMs: 5000, // 5 seconds
},
})
Live
If immediate updates are required you can use the live strategy. This strategy is only available on certain plans and can have additional charges depending on total connection minutes.
const connection = await FeatureBoardService.init('<your environment key', {
updateStrategy: 'live',
})

Specifying initial values

If you would like to manually specify the last known good set of features values, the SDK will start using those values if it can't connect to the service.
import { FeatureBoardService, MemoryFeatureStore } from '@featureboard/node-sdk'
const connection = await FeatureBoardService.init('<your environment key>', {
store: new MemoryFeatureStore([
{
featureKey: 'my-feature-key',
audienceExceptions: [{ audienceKey: 'plan-pro', value: true }],
defaultValue: false,
},
]),
})

Persistent storage

In the unlikely event that your application cannot connect to FeatureBoard, it can be a good idea to setup persistent storage for feature values. This allows the FeatureBoard SDK to fall back to the last known good configuration in the case of a connection failure.
Currently we only support the in memory store, but in the future we will release packages on NPM to support other storage options. You can implement your own though!
Implementing your own store
import { FeatureStore } from '@featureboard/node-sdk'
import fs from 'fs'
import fsAsync from 'fs/promises'
export class FileFeatureStore implements FeatureStore {
private _store: Record<string, FeatureValues | undefined> = {}
isInitialised: boolean
constructor() {
if (fs.existsSync('/tmp/featureboardstate.json')) {
this._store = JSON.parse(fs.readFileSync('/tmp/featureboardstate.json').toString())
isInitialised = true
}
for (const value of initialValues || []) {
this._store[value.featureKey] = value
}
}
all(): Record<string, FeatureValues | undefined> {
return { ...this._store }
}
get(featureKey: string): FeatureValues | undefined {
return this._store[featureKey]
}
async set(featureKey: string, value: FeatureValues | undefined): Promise<void | PromiseLike<any>> {
await fsAsync.writeFile('/tmp/featureboardstate.json', JSON.stringify(this._store))
this._store[featureKey] = value
}
}

Universal JavaScript applications

For universal JavaScript applications where you want to use the SDK on the server and client, the SDK returned from the request message is the same shape as the client from @featureboard/js-sdk, making FeatureBoard SDKs easy to use with frameworks like Next.js.

TypeScript

When using TypeScript add an ambient type definition using Declaration Merging typing your features, for example
declare module '@featureboard/js-sdk' {
interface Features {
'test-feature-1': boolean
'test-feature-2': string
'test-feature-2b': string
'test-feature-3': number
}
}
If you do not want to specify all your features the features you can just add:
declare module '@featureboard/js-sdk' {
interface Features extends Record<string, string | number | boolean> {}
}
Copy link
On this page
Installation
Usage
Universal JavaScript applications
TypeScript