Feature Flags
Feature flags allow you to enable, disable, or configure features in Pepr. They provide a way to manage feature rollouts, toggle experimental features, and maintain configuration across different environments. Feature flags work across both CLI and in-cluster environments, using the same underlying implementation.
Pepr’s feature flag system supports:
- Boolean flags
- String values
- Numeric values
- Default values for flags
- Type safety through TypeScript
- Configuration via environment variables
- Configuration via initialization strings
- Consistent behavior in both CLI and in-cluster environments
Best Practices
Section titled “Best Practices”- Temporary Usage: Use feature flags for temporary changes, gradual rollouts, or experimental features. Do NOT use feature flags for permanent configuration.
- Descriptive Names: Choose descriptive flag names and provide detailed descriptions in the metadata.
- Default Values: Always provide sensible default values for feature flags.
- Type Safety: Leverage TypeScript’s type system when accessing feature flags.
- Cleanup: Remove feature flags that are no longer needed to maintain a clean codebase and stay within the feature flag limit.
Getting Started
Section titled “Getting Started”Using Feature Flags
Section titled “Using Feature Flags”-
Enable a CLI feature flag via environment variable:
Terminal window PEPR_FEATURE_REFERENCE_FLAG=true npx pepr@latest -
Enable a CLI feature flag via argument:
Terminal window npx pepr@latest --features="reference_flag=true" -
Configure feature flags for a Pepr module: Add to your
package.json
:"pepr": {"env": {"PEPR_FEATURE_REFERENCE_FLAG": true}}
Defining Feature Flags
Section titled “Defining Feature Flags”Feature flags in Pepr are defined in the FeatureFlags
object.
The FeatureFlags
object is the source of truth for all available feature flags.
Feature Flags have:
- A unique key used for programmatic access
- Metadata containing name, description, and default value
Feature flag values are converted to appropriate types:
"true"
and"false"
strings are converted to boolean values- Numeric strings are converted to numbers
- All other values remain as strings
Example definition:
export const FeatureFlags: Record<string, FeatureInfo> = { REFERENCE_FLAG: { key: "reference_flag", metadata: { name: "Reference Flag", description: "A feature flag to show intended usage.", defaultValue: false, }, },};
Configuration and Workflows
Section titled “Configuration and Workflows”Feature flags are configured in two ways for either CLI or Module use.
Only feature flags defined in the FeatureFlags
object can be configured.
Attempting to use an undefined flag will result in an error.
Pepr CLI Workflow
Section titled “Pepr CLI Workflow”-
Using environment variables with the format
PEPR_FEATURE_<FLAG_NAME>
:Terminal window # Run Pepr with debug logging to verify feature flagsPEPR_FEATURE_REFERENCE_FLAG=true LOG_LEVEL=debug npx pepr@latest -
Using the
--features
CLI argument:Terminal window LOG_LEVEL=debug npx pepr@latest --features="reference_flag=true"
Pepr Module Deployment Workflow
Section titled “Pepr Module Deployment Workflow”For deployed modules, configure feature flags in the module’s package.json
:
"pepr": { "env": { "PEPR_FEATURE_REFERENCE_FLAG": true } },
Build and deploy the module once environment variables are set with a known $APP_NAME
:
# Edit your package.json to include feature flagsjq '.pepr.env.PEPR_FEATURE_REFERENCE_FLAG = true' package.json
npx pepr@latest buildnpx pepr@latest deploy -i pepr:dev
APP_NAME=pepr-module-namekubectl logs -n pepr-system --selector app=$APP_NAME | grep "Feature flags store initialized"
Troubleshooting
Section titled “Troubleshooting”Feature Flag Not Recognized
Section titled “Feature Flag Not Recognized”If your feature flag isn’t recognized:
- Verify the flag is defined in the
FeatureFlags
object - Check the case of the environment variable (
PEPR_FEATURE_REFERENCE_FLAG
vspepr_feature_reference_flag
) - Ensure correct format for CLI flags (
reference_flag=true
notREFERENCE_FLAG=true
)
Too Many Feature Flags
Section titled “Too Many Feature Flags”If you receive the error: Error: Too many feature flags active: 5 (maximum: 4)
- Review active feature flags using
featureFlagStore.getAll()
- Remove or consolidate unnecessary feature flags
- Consider if some flags could be regular configuration instead
Flag Value Incorrect Type
Section titled “Flag Value Incorrect Type”If your feature flag has an unexpected type:
- Remember that strings
"true"
and"false"
are automatically converted to booleans - Numeric strings are automatically converted to numbers
- Use explicit type checking in your code:
typeof featureFlagStore.get(...)
For Maintainers
Section titled “For Maintainers”Development Guidelines
Section titled “Development Guidelines”Accessing and Implementing Feature Flags
Section titled “Accessing and Implementing Feature Flags”To add a new feature flag, update the FeatureFlags
object in the source code.
Any feature flag not defined in this object cannot be used in the application.
Access feature flags the same way in both CLI and in-cluster environments using the featureFlagStore
.
This snippet shows how to execute different code paths based upon a feature flag value.
To execute within the Pepr project, save the snippet to file.ts
and run npx tsx file.ts
.
import { featureFlagStore } from "./lib/features/store";import { FeatureFlags } from "./lib/features/FeatureFlags";
// Get a boolean flagconst isReferenceEnabled = featureFlagStore.get(FeatureFlags.REFERENCE_FLAG.key);
const allFlags = featureFlagStore.getAll();
// Use feature flags for conditional logicif (featureFlagStore.get(FeatureFlags.REFERENCE_FLAG.key)) { Log.info(`Flag value: ${isReferenceEnabled} of type ${typeof featureFlagStore.get(FeatureFlags.REFERENCE_FLAG.key)}`)} else { Log.info(`All flags: ${JSON.stringify(allFlags)}`)}