FeatureFlags
🚩 Allows developers to configure feature flags, run multiple A/B tests or phase feature roll out using a JSON configuration file.
Install / Use
/learn @rwbutler/FeatureFlagsREADME

FeatureFlags makes it easy to configure feature flags, A/B and MVT tests via a JSON file which may be bundled with your app or hosted remotely. For remotely-hosted configuration files, you may enable / disable features without another release to the App Store, update the percentages of users in A/B test groups or even roll out a feature previously under A/B test to 100% of your users once you have decided that the feature is ready for prime time.
To learn more about how to use FeatureFlags, take a look at the keynote presentation, check out the blog post, or make use of the table of contents below:
Features
- [x] Feature flags
- [x] A/B testing and MVT testing
- [x] Feature A/B testing (where a feature is enabled vs a control group without the feature)
- [x] Host your feature flags JSON configuration remotely allowing you to enable / disable features without releasing a new version of your app
- [x] Use an existing JSON file or host an entirely new configuration
- [x] Adjust the percentages of users in each test group remotely
- [x] Convert an A/B test into a feature flag once you have decided whether the feature test was a success i.e. rollout a feature to 100% of users
- [x] Visualize the state of your flags and tests using FeatureFlagsViewController in debug builds of your app
What's new in FeatureFlags 3.0.0?
See CHANGELOG.md.
Installation
Cocoapods
CocoaPods is a dependency manager which integrates dependencies into your Xcode workspace. To install it using RubyGems run:
gem install cocoapods
To install FeatureFlags using Cocoapods, simply add the following line to your Podfile:
pod "FeatureFlags"
Then run the command:
pod install
For more information see here.
Carthage
Carthage is a dependency manager which produces a binary for manual integration into your project. It can be installed via Homebrew using the commands:
brew update
brew install carthage
In order to integrate FeatureFlags into your project via Carthage, add the following line to your project's Cartfile:
github "rwbutler/FeatureFlags"
From the macOS Terminal run carthage update --platform iOS to build the framework then drag FeatureFlags.framework into your Xcode project.
For more information see here.
Swift Package Manager
The Swift Package Manager is a dependency manager for Swift modules and is included as part of the build system as of Swift 3.0. It is used to automate the download, compilation and linking of dependencies.
To include FeatureFlags as a dependency within a Swift package, add the package to the dependencies entry in your Package.swift file as follows:
dependencies: [
.package(url: "https://github.com/rwbutler/FeatureFlags.git", from: "2.0.0")
]
Usage
With the framework integrated into your project, the next step is configuration using a JSON file which may be bundled as part of your app or hosted remotely. The JSON file may be newly-created or could be an existing configuration JSON file that you're using already. Simply add a key called features at the top level of your file mapping to an array of features as follows:
{
"features": []
}
The contents of the array depends on the feature flags and tests to be configured.
To let FeatureFlags know where to find your configuration file:
guard let featuresURL = Bundle.main.url(forResource: "features", withExtension: "json") else { return }
FeatureFlags.configurationURL = featuresURL
Or:
guard let featuresURL = URL(string: "https://www.exampledomain.com/features.json") else { return }
FeatureFlags.configurationURL = featuresURL
In the event that you opt to host your JSON file remotely, you may provide a bundled fallback as part of your app bundle:
guard let fallbackURL = Bundle.main.url(forResource: "features", withExtension: "json") else { return }
FeatureFlags.localFallbackConfigurationURL = fallbackURL
Your remotely-hosted JSON file will always take precedence over bundled settings and remotely-defined settings will be cached so that in the eventuality that the user is offline, the last settings retrieved from the network will be applied.
Feature Flags
In order to configure a feature flag add a feature object to the features array in your JSON configuration.
{
"features": [{
"name": "Example Feature Flag",
"enabled": false
}]
}
Then add an extension on Feature.Name to import your feature flag in code as follows:
import FeatureFlags
extension Feature.Name {
static let exampleFeatureFlag = Feature.Name(rawValue: "Example Feature Flag")
}
Make sure that the raw value matches the string in your JSON file. Then call the following to check whether the feature flag is enabled:
Feature.isEnabled(.exampleFeatureFlag))
If the string specified in your Feature.Name extension doesn't match the value in your JSON file, the default value returned is false. If you need to check the feature exists, you can write:
if let feature = Feature.named(.exampleFeatureFlag) {
print("Feature name -> \(feature.name)")
print("Feature enabled -> \(feature.isEnabled())")
}
A/B Tests
To configure an A/B test, add the following feature object to the features array in your JSON file:
{
"name": "Example A/B Test",
"enabled": true,
"test-variations": ["Group A", "Group B"]
}
enabledindicates whether or not the A/B test is enabled.
The only difference between a feature flag and an A/B test involves adding an array of test variations. FeatureFlags will assume that you are configuring an A/B test if you add two test variations to the array - add any more and the test will automatically become a multivariate test (MVT).
Import your feature into code with an extension on Feature.Name:
extension Feature.Name {
static let exampleABTest = Feature.Name(rawValue: "Example A/B Test")
}
And then use the following to check which group the user has been assigned to:
if let test = ABTest(rawValue: .exampleABTest) {
print("Is in group A? -> \(test.isGroupA())")
print("Is in group B? -> \(test.isGroupB())")
}
Alternatively, you may prefer the following syntax:
if let feature = Feature.named(.exampleABTest) {
print("Feature name -> \(feature.name)")
print("Is group A? -> \(feature.isTestVariation(.groupA))")
print("Is group B? -> \(feature.isTestVariation(.groupB))")
print("Test variation -> \(feature.testVariation())")
}
Feature A/B Tests
A feature A/B test is a subtle variation on (and subtype of) an A/B test. In a generic A/B test you may want to check whether a user has been placed in the blue background or red background test variation. A feature A/B test specifically tests whether the introduction of a new feature is an improvement over a control group without the feature. Thus in a feature A/B test - the feature is either off or on.
To configure a feature A/B test use the following JSON:
{
"name": "Example Feature A/B Test",
"enabled": true,
"test-variations": ["Enabled", "Disabled"]
}
enabledindicates whether or not the A/B test is enabled.
extension Feature.Name {
static let exampleFeatureABTest = Feature.Name(rawValue: "Example Feature A/B Test")
}
By naming the test variations Enabled and `Di
Related Skills
node-connect
335.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
82.5kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
335.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
82.5kCommit, push, and open a PR
