Feature Flag Service Tutorial · Module 04 of 10

SDK Integration & Clients

Build SDKs for Node.js and JavaScript so applications can easily check flags. Cache flag definitions locally with periodic updates. Support offline evaluation. By the end, any app can integrate flags with a few lines of code.

~4–5 hrsIntermediateSDK focus
← Back to Module 04 overview
What You'll Have at the End

Definition of Done

  • Node.js SDK: FeatureFlagClient class with isEnabled(flagName, context) method.
  • Local caching: Flags refreshed every 60 seconds (configurable).
  • Offline support: Cached flags work even if service is temporarily unavailable.
  • npm install @feature-flag-service/sdk (published or local monorepo).
  • JavaScript/Browser SDK with same interface.
  • Metrics: Cache hit rate, evaluation latency, flag refresh failures.
  • Example usage in demo app.
The Steps

Build It

STEP 1

Create Node.js SDK

Create sdk/node/src/client.ts:

import axios from 'axios';

interface Flag {
  id: string;
  name: string;
  status: string;
  rules: any[];
}

export interface EvaluationContext {
  user_id?: string;
  segment?: string;
  attributes?: Record;
}

export class FeatureFlagClient {
  private apiUrl: string;
  private clientId: string;
  private flags: Map = new Map();
  private lastRefresh: number = 0;
  private refreshInterval: number;
  private cacheHits: number = 0;
  private cacheMisses: number = 0;

  constructor(apiUrl: string, clientId: string, refreshInterval = 60000) {
    this.apiUrl = apiUrl;
    this.clientId = clientId;
    this.refreshInterval = refreshInterval;
    this.startRefresh();
  }

  async isEnabled(flagName: string, context: EvaluationContext = {}): Promise {
    try {
      const response = await axios.post(
        `${this.apiUrl}/flags/${flagName}/evaluate`,
        context,
        { headers: { 'X-Client-ID': this.clientId } }
      );
      return response.data.enabled;
    } catch (err) {
      console.error(`Failed to evaluate flag ${flagName}:`, err);
      return false;
    }
  }

  private async startRefresh() {
    setInterval(async () => {
      try {
        const response = await axios.get(`${this.apiUrl}/flags`, {
          headers: { 'X-Client-ID': this.clientId }
        });
        this.flags.clear();
        response.data.flags.forEach((flag: Flag) => {
          this.flags.set(flag.name, flag);
        });
        this.lastRefresh = Date.now();
      } catch (err) {
        console.error('Failed to refresh flags:', err);
      }
    }, this.refreshInterval);
  }

  getMetrics() {
    return {
      cacheHits: this.cacheHits,
      cacheMisses: this.cacheMisses,
      cachedFlags: this.flags.size,
      lastRefresh: new Date(this.lastRefresh)
    };
  }
}