Basic Usage Example
This example demonstrates a complete Flagify integration in an Express.js application. It covers initialization, flag evaluation, and cleanup.
Setup
// flagify.ts
import { Flagify } from '@flagify/node';
export const flagify = new Flagify({
projectKey: 'my-project',
publicKey: process.env.FLAGIFY_PUBLIC_KEY!,
options: {
realtime: true,
},
});
Wait for the initial sync before handling requests:
await flagify.ready();
Express middleware
Create a middleware that attaches flag evaluation to each request:
// middleware/flags.ts
import { flagify } from '../flagify';
import type { Request, Response, NextFunction } from 'express';
export function flagsMiddleware(
req: Request,
res: Response,
next: NextFunction
) {
// Attach flag helpers to request
req.flags = {
isEnabled: (flag: string) => flagify.isEnabled(flag),
getValue: <T>(flag: string) => flagify.getValue<T>(flag),
};
next();
}
Route handlers
Use flags in your route handlers:
// routes/checkout.ts
app.get('/checkout', (req, res) => {
const useNewCheckout = req.flags.isEnabled('new-checkout-flow');
const maxItems = req.flags.getValue<number>('cart-max-items', 50);
if (useNewCheckout) {
res.render('checkout-v2', { maxItems });
} else {
res.render('checkout', { maxItems });
}
});
Gradual rollout pattern
A common pattern is to gradually roll out a feature while monitoring metrics:
app.get('/api/search', (req, res) => {
const useNewSearch = req.flags.isEnabled('new-search-engine');
const startTime = Date.now();
let results;
if (useNewSearch) {
results = await newSearchEngine.query(req.query.q);
} else {
results = await legacySearch.query(req.query.q);
}
const duration = Date.now() - startTime;
// Track performance by variant for comparison
metrics.record('search_latency', duration, {
engine: useNewSearch ? 'new' : 'legacy',
});
res.json(results);
});
Graceful shutdown
Disconnect the realtime listener when the server shuts down:
process.on('SIGTERM', () => {
flagify.destroy();
server.close();
});