The Evaluation Context is a crucial concept in Flagdeck that allows you to target feature flags to specific users, sessions, or environments. This guide explains how to structure and use context objects effectively.
An evaluation context in Flagdeck follows this structure:
const context = {
// Unique user identifier
userId: string,
// Optional session identifier
sessionId?: string,
// Custom attributes for targeting
attributes?: {
[key: string]: any
}
};
When no context is provided, the flag will use default targeting rules:
// No context - uses default rules
const isEnabled = await flagdeck.isEnabled('new-feature');
The simplest form of context includes just a user ID:
// User ID only
const isEnabled = await flagdeck.isEnabled('new-feature', {
userId: 'user-123'
});
A complete context with user ID and attributes:
// Complete context
const isEnabled = await flagdeck.isEnabled('new-feature', {
userId: 'user-456',
sessionId: 'session-789',
attributes: {
country: 'US',
plan: 'premium',
isAdmin: true,
lastLoginDate: '2023-04-15'
}
});
Attributes are key-value pairs used in targeting rules. They can be categorized as follows:
Attributes that describe the user:
const context = {
userId: 'user-123',
attributes: {
// User demographics
email: '[email protected]',
name: 'John Smith',
age: 28,
// Account information
plan: 'premium',
accountType: 'business',
isAdmin: true,
signupDate: '2022-01-15',
// Location information
country: 'US',
region: 'West',
timezone: 'America/Los_Angeles',
// User preferences
language: 'en',
theme: 'dark',
notifications: 'enabled'
}
};
Attributes related to business metrics:
const context = {
userId: 'user-123',
attributes: {
// User engagement
lastLoginDate: '2023-04-15',
totalLogins: 47,
sessionCount: 152,
daysActive: 28,
// Purchase behavior
purchaseCount: 5,
totalSpend: 125.50,
averageOrderValue: 25.10,
lastPurchaseDate: '2023-03-22',
// Feature usage
hasUsedFeatureX: true,
featureYUsageCount: 12
}
};
Attributes about the technical environment:
const context = {
userId: 'user-123',
attributes: {
// Device information
deviceType: 'mobile',
deviceModel: 'iPhone 14',
osName: 'iOS',
osVersion: '16.2',
// Browser/app information
browser: 'Chrome',
browserVersion: '110.0.5481.177',
appVersion: '2.5.0',
// Network information
connectionType: '5G',
isp: 'Verizon'
}
};
You should maintain consistent context across user sessions. Here are common patterns:
// Initialize context when user signs in
const userContext = {
userId: user.id,
attributes: {
email: user.email,
plan: user.subscriptionPlan,
country: user.country,
// Add more attributes as needed
}
};
// Store in application state (Redux, Context API, etc.)
store.dispatch(setFlagContext(userContext));
// Use throughout the application
function MyComponent() {
const flagContext = useSelector(state => state.flags.context);
const [isFeatureEnabled, setIsFeatureEnabled] = useState(false);
useEffect(() => {
async function checkFlag() {
const enabled = await flagdeck.isEnabled('new-feature', flagContext);
setIsFeatureEnabled(enabled);
}
checkFlag();
}, [flagContext]);
// ...
}
// Initialize on app launch or login
const initializeContext = async (user) => {
const context = {
userId: user.id,
attributes: {
email: user.email,
plan: user.plan,
deviceType: Platform.OS,
appVersion: DeviceInfo.getVersion(),
// Additional attributes
}
};
// Save to async storage for persistence
await AsyncStorage.setItem('flagdeck_context', JSON.stringify(context));
return context;
};
// Retrieve context when needed
const getContext = async () => {
try {
const storedContext = await AsyncStorage.getItem('flagdeck_context');
return storedContext ? JSON.parse(storedContext) : null;
} catch (e) {
console.error('Failed to get context', e);
return null;
}
};
// For user-specific context in server applications
app.use(async (req, res, next) => {
if (req.user) {
req.flagContext = {
userId: req.user.id,
attributes: {
role: req.user.role,
plan: req.user.plan,
// Add more attributes
}
};
}
next();
});
// Use in route handlers
app.get('/dashboard', async (req, res) => {
const showNewDashboard = await flagdeck.isEnabled(
'new-dashboard',
req.flagContext
);
res.render('dashboard', {
showNewDashboard
});
});
The Flagdeck SDK automatically enriches your context with additional information:
// What you provide
const context = {
userId: 'user-123'
};
// What actually gets sent (automatic enrichment)
{
userId: 'user-123',
attributes: {
sdk_platform: 'web',
browser_name: 'chrome',
browser_version: '110.0.5481.177',
language: 'en-US',
screen_width: 1920,
screen_height: 1080,
timezone: 'America/New_York',
is_mobile: false
}
}
// React Native automatic enrichment
{
userId: 'user-123',
attributes: {
sdk_platform: 'mobile',
mobile_os: 'ios',
user_agent: '...',
react_native_version: '0.68.2'
}
}
// Node.js automatic enrichment
{
userId: 'user-123',
attributes: {
sdk_platform: 'server',
node_version: 'v16.14.0',
platform: 'linux',
arch: 'x64',
memory_usage_mb: 256,
timezone: 'UTC'
}
}
Whenever possible, include a consistent user ID to enable proper targeting and consistency:
// Good - with user ID
const context = { userId: 'user-123' };
// Avoid if possible - anonymous context
const context = { attributes: { country: 'US' } };
Keep attribute types consistent across evaluations:
// Consistent: Always using boolean for isAdmin
context.attributes.isAdmin = true;
// Inconsistent: Switching between boolean and string
context.attributes.isAdmin = 'true'; // Bad practice
Keep context objects reasonably sized to improve performance:
// Good: Focused attributes
const context = {
userId: 'user-123',
attributes: {
plan: 'premium',
country: 'US'
}
};
// Avoid: Excessive attributes
const context = {
userId: 'user-123',
attributes: {
// Dozens of attributes that might not be used for targeting
...allUserProperties,
...allDeviceProperties,
...allHistoricalData
}
};
Create the context object once and reuse it:
// Good: Create once and reuse
const userContext = buildUserContext(currentUser);
// Multiple evaluations with the same context
const isFeatureAEnabled = await flagdeck.isEnabled('feature-a', userContext);
const isFeatureBEnabled = await flagdeck.isEnabled('feature-b', userContext);
Update the context when important attributes change:
// Update context when user upgrades
function handleSubscriptionUpgrade(newPlan) {
userContext.attributes.plan = newPlan;
userContext.attributes.upgradedAt = new Date().toISOString();
// Re-evaluate any flags that might be affected
checkFeatureEligibility();
}
For better type safety, use the EvaluationContext
type:
import { Flagdeck, EvaluationContext } from '@flagdeck/js';
// Partial context type
const context: Partial<EvaluationContext> = {
userId: 'user-123',
attributes: {
plan: 'premium',
isAdmin: true,
signupDate: '2022-01-15'
}
};
// Type safety for attributes
interface UserAttributes {
plan: string;
isAdmin: boolean;
signupDate: string;
}
const typedContext: Partial<EvaluationContext> = {
userId: 'user-123',
attributes: {
plan: 'premium',
isAdmin: true,
signupDate: '2022-01-15'
} as UserAttributes
};
Start using Flagdeck today
Simple feature flag management for modern development teams.
Product
© 2025 Flagdeck. All rights reserved.