FF4k
The primary entry point and facade for the FF4K feature flag library.
FF4K provides a coroutine-safe, Kotlin Multiplatform feature flag and configuration management system. This class serves as the main API for all feature flag operations, delegating storage concerns to pluggable FeatureStore and PropertyStore implementations.
Key Features
Feature Flags: Enable, disable, and check feature states with optional flipping strategies
Properties: Type-safe configuration properties with support for various data types
Groups: Organize features into logical groups for bulk operations
Auto-Create Mode: Automatically create missing features on first access
Flipping Strategies: Conditional feature activation based on runtime context
Architecture
FF4K follows a facade pattern, providing a unified API while delegating to:
FeatureStore: Manages feature flag persistence and retrieval
PropertyStore: Manages configuration property persistence and retrieval
Both stores default to in-memory implementations but can be replaced with persistent backends (Redis, databases, etc.) by implementing the respective interfaces.
Thread Safety
All operations are suspend functions designed for use with Kotlin coroutines. Internal state is protected using Mutex for coroutine-safe concurrent access. The stores themselves are responsible for their own thread-safety guarantees.
Context Resolution
When checking features with FlippingStrategy, context is resolved in priority order:
Explicit FlippingExecutionContext passed to check
Implicit context from withFlippingContext coroutine scope
Empty context (when neither is provided)
Example Usage
Basic Feature Checking
val ff4k = FF4k()
// Add and check features
ff4k.addFeature("dark-mode", isEnabled = true)
if (ff4k.check("dark-mode")) {
enableDarkMode()
}
// Toggle features
ff4k.enable("beta-feature")
ff4k.disable("legacy-feature")Using Flipping Strategies with Context
// Feature with percentage rollout strategy
val feature = Feature(
uid = "new-checkout",
isEnabled = true,
flippingStrategy = PercentageStrategy(mapOf("percentage" to "25"))
)
ff4k.addFeature(feature)
// Check with explicit context
val context = FlippingExecutionContext(ContextKeys.USER_ID to "user-123")
val isEnabled = ff4k.check("new-checkout", context)
// Or use coroutine context propagation
withFlippingContext(FlippingExecutionContext(ContextKeys.USER_ID to "user-123")) {
val isEnabled = ff4k.check("new-checkout") // context automatically available
}Working with Groups
ff4k.addFeature(Feature("feature-a", isEnabled = false, group = "experiment-1"))
ff4k.addFeature(Feature("feature-b", isEnabled = false, group = "experiment-1"))
// Enable all features in a group at once
ff4k.enableGroup("experiment-1")
// Query features by group
val experimentFeatures = ff4k.featuresByGroup("experiment-1")Auto-Create Mode
// With autoCreate enabled, missing features are created on first access
val ff4k = FF4k(autoCreate = true)
// This won't throw - creates a disabled feature automatically
val isEnabled = ff4k.check("non-existent-feature") // returns falseConfiguration Properties
ff4k.addProperty(PropertyString("api.url", "https://api.example.com"))
ff4k.addProperty(PropertyInt("max.retries", 3))
val apiUrl: Property<String>? = ff4k.property("api.url")
val maxRetries: String? = ff4k.propertyAsString<Int>("max.retries")See also
Constructors
Types
Describes the origin or integration point from which this FF4k instance is accessed.
Properties
When true, automatically creates missing features as disabled on first access. When false, throws FeatureNotFoundException for missing features.
The store managing feature flag persistence. Defaults to InMemoryFeatureStore.
The store managing property persistence. Defaults to InMemoryPropertyStore.
Identifies the source/client type making API calls. Used for auditing and analytics.
Functions
Adds a feature to the store.
Creates and adds a new feature to the store.
Adds a property to the store.
Check if a feature is enabled.
Checks whether a group with the given name exists in the store.
Removes a feature from the store.
Removes a property from the store.
Get all disabled features.
Disables all features belonging to a specific group.
Get all enabled features.
Enables all features belonging to a specific group.
Retrieves all features belonging to a specific group.
Get features with a specific permission.
Get features with a flipping strategy.
Checks whether a feature exists in the store.
Checks whether a property exists in the store.
Execute one block if the feature is enabled, another if disabled.
Retrieves all properties from the store.
Retrieves a property value as a string representation.
Get statistics about features.
Execute a block with side effects if the feature is enabled.