Optimizely Feature Flag Migration Guide
- 
Install the Eppo SDK - 
Login to Eppo with your work email: https://eppo.cloud/ 
- 
Generate an SDK key by navigating to “SDK Keys” under Configuration 
- 
Define a logging function for the Eppo SDK to log assignments so they end up in your data warehouse TypeScript Example: const assignmentLogger: IAssignmentLogger = {
 logAssignment(assignment) {
 analytics.track({
 userId: assignment.subject,
 event: "Eppo Randomization Event",
 type: "track",
 properties: { ...assignment },
 });
 },
 };
- 
Initialize the SDK in your code using the SDK guides for your language here TypeScript Example: await init({
 apiKey: EPPO_SDK_KEY,
 assignmentLogger,
 });
 
- 
- 
Set up a new flag and verify its functionality - 
Create a new flag in Eppo by navigating to “Feature Flags” under Configuration 
- 
Implement the flag in your application code 
- 
Test the flag in your local development environment to ensure it works as expected. TypeScript Example: const variation = getInstance().getStringAssignment(
 "<SUBJECT-KEY>",
 "<FLAG-KEY>",
 {
 // Optional map of subject metadata for targeting.
 }
 );
- 
Deploy the application to your staging or testing environments and verify the flag's functionality. 
- 
Once verified, deploy the application to your production environment and test the flag again. 
 
- 
- 
Identify critical flags in Optimizely - Make a list of all the feature flags currently in use within your application using the provided template
- Categorize the flags as critical or non-critical based on their importance and impact on your application's functionality.
- Flags that are disabled or are rolled out to 100% can be categorized as non-critical
 
- 
Remove existing flag code for all non-critical flags - For the non-critical flags identified in the previous step, remove the flag code from your application.
- Test your application thoroughly to ensure that the removal of these flags does not introduce any regressions or unintended behavior.
 
- 
Create a fallback value for critical flags - 
Implement a function that wraps calling Eppo’s SDK to have a fallback mechanism to use the Optimizely flag values if the new service is unavailable or experiences issues. 
- 
When attempting to retrieve a flag value from Eppo, catch any exceptions or errors that may occur due to service unavailability or issues and return the old value. TypeScript Example: // After initialization, turn off graceful failure so exceptions are rethrown
 getInstance().setIsGracefulFailureMode(false);
 // Drop-in wrapper replacement for isFeatureEnabled()
 export function isFeatureEnabledWrapper(
 featureKey: string,
 userId: string,
 attributes?: Record<string, string | number | boolean | null>
 ) {
 let isEnabled = false;
 try {
 // For grouping values with a single flag, JSON-typed variations are used
 isEnabled = getInstance().getBooleanAssignment(
 userId,
 featureKey,
 attributes
 ) ?? false;
 } catch (e) {
 logger.warn(
 'Error encountered evaluating boolean assignment from Eppo SDK; falling back to optimizely',
 { featureKey, userId, attributes }
 );
 isEnabled = optimizelyClientInstance.isFeatureEnabled(
 featureKey,
 userId,
 attributes
 );
 }
 return isEnabled;
 }
 // Drop-in wrapper replacement for getFeatureVariableString()
 export function getFeatureVariableStringWrapper(
 featureKey: string,
 variableKey: string,
 userId: string,
 attributes?: Record<string, string | number | boolean | null>
 ) {
 let assignment: string | null = null;
 try {
 // For grouping values with a single flag, JSON-typed variations are used
 const featureVariables = getInstance().getParsedJSONAssignment(
 userId,
 featureKey,
 attributes
 ) as Record<string, string | number | boolean | null>;
 // Look up the desired specific value
 assignment = featureVariables?.[variableKey]?.toString() ?? null;
 } catch (e) {
 logger.warn(
 'Error encountered evaluating assignment from Eppo SDK; falling back to optimizely',
 { featureKey, variableKey, userId, attributes }
 );
 assignment = optimizelyClientInstance.getFeatureVariableString(
 featureKey,
 variableKey,
 userId,
 attributes
 );
 }
 return assignment;
 }
 
- 
- 
Recreate existing flags in Eppo - In the Eppo dashboard, recreate the critical flags from Optimizely.
- Ensure that the flag configurations, such as rollout percentages, targeting rules, and variations, are accurately replicated in the new service.
 
- 
Switch existing flags to the new application - 
Once you have verified that the Eppo flags are working correctly, switch your application to use the function that checks Eppo for flags instead of the Optimizely ones. 
- 
Remove the fallback mechanism and the Optimizely flag code once you have confirmed that the Eppo flags are working as expected in production. 
- 
It’s recommended to keep the wrapper as a facade to make future changes easier, as they will typically only need to be made to the wrapper. TypeScript Example: // FeatureHelper.ts
 export function isFeatureEnabledWrapper(
 featureKey: string,
 userId: string,
 attributes?: Record<string, string | number | boolean | null>
 ) {
 return getInstance().getBooleanAssignment(userId, featureKey, attributes) ?? false;
 }// PlaceUsingFlags.ts
 const useBigButtons = isFeatureEnabledWrapper(userId, 'use-big-buttons', userAttributes);
 Appendix: TypeScript Implementation ComparisonOptimizely and Eppo have very similar interfaces, making switching from one to the other straightforward. Note: Above each code example is a link to its respective documentation source. Initializationconst optimizelyClientInstance = optimizelySdk.createInstance({
 datafile: window.optimizelyDatafile,
 });Eppo: await init({
 apiKey: EPPO_SDK_KEY
 });Wiring Up Assignment Loggeroptimizely.notificationCenter.addDecisionNotificationListener(decisionListener: { (type, userId, attributes, decisionInfo) in
 // Send data to analytics provider / warehouse here
 })Eppo: const assignmentLogger: IAssignmentLogger = {
 logAssignment(assignment) {
 // Send data to analytics provider / warehouse here
 }
 };
 getInstance().setLogger(assignmentLogger); // Note: can also be set in init()Getting a Boolean FlagFor example, checking if a feature is enabled const enabled =
 optimizelyClientInstance.isFeatureEnabled(featureKey, userId, attributes);*Eppo:* const enabled =
 getInstance().getBooleanAssignment(userId, featureKey, attributes) ?? false;Getting a String Valueconst value =
 getFeatureVariableString(featureKey, variableKey, userId, attributes)Eppo: 
 // If it's part of a multi-valued variation (How Optimizely organizes values)
 const value =
 getInstance().getParsedJSONAssignment(userId, featureKey, attributes)?.[variableKey];
 
 // If it's a stand-alone string variation value (Eppo only)
 const value =
 getInstance().getStringAssignment(userId, featureKey, attributes);Getting All Values of a Multi-Valued Flag VariationFor example, getting all variables for a feature const values =
 optimizelyClient.getAllFeatureVariables(featureKey, userId, attributes);Eppo: const values =
 getInstance().getParsedJSONAssignment(userId, featureKey, attributes);
-