Feature toggles
Feature toggles let us ship unfinished work safely by hiding it behind a runtime switch. Instead of long-lived branches, we merge small increments and control exposure via toggles, so release cadence stays predictable.
Easy Features overview
EasyFeature (see easy_lib/easy_features/easy_feature.rb) is built on top of Flipper.
Every toggle has to be registered once. It is registered through the EasyFeatures::Registry, and then evaluated via EasyFeature.enabled?.
Key points:
- Toggles are registered as symbols (e.g.
:ai_project_planner) with metadata such as owners,introduced_in, status, and trackingref_id. EasyFeature.enabled?delegates to Flipper and caches the decision per actor usingEasyFeature::CACHE_TTLto reduce Redis chatter.- Unknown keys short-circuit to
falseto avoid surprises; verification happens throughEasyFeatures.known?inside the helper. - Redis/Flipper outages are caught and logged, returning
falseso the platform fails closed.
Registering a feature
All toggles must be registered exactly once before they can be queried. Registration usually happens in the engine/plugin entry point or an initializer that runs during boot.
| easy_features/registry | |
|---|---|
Guidelines:
keymust be a non-empty symbol. Duplicates raise immediately.ownersis a list of teams, never individuals.introduced_inandtarget_versionfollow the platform version scheme and are validated byGem::Version.ref_idid of a related task in ESkostatusexperimental, beta, stable, released, use experimental as default. Keep updated as the feature evolves.
Usage patterns
The recommended ergonomics mirror the legacy approach: expose an engine-level helper wrapping EasyFeature.enabled?, then use it in controllers, jobs, or services.
| engine module | |
|---|---|
class MyFeatureController < ApplicationController
before_action :ensure_feature
private
def ensure_feature
render_404 unless MyEngine.my_feature_enabled?
end
end
Notes:
- You can enable a feature for explicit actors when needed. The most common actor is
User, but it can beProjector other classes as well. The Flipper ID follows the formatClass;ID, e.g.User;28628orProject;42. - You can layer environment-specific shortcuts, e.g. always return
truein development to avoid toggling during local work. - Because results are cached per actor for
EasyFeature::CACHE_TTL, avoid manual caching unless you need tighter control.
Naming and conventions
- Use short, descriptive symbol keys (
:issue_suggestions,:new_editor). - Prefix helper methods with the feature name plus
_enabled?for readability. - Keep descriptions and statuses up to date; the registry doubles as living documentation.
Legacy active? API
EasyFeature.active? still exists for historical ENV-only toggles and now emits a deprecation warning urging you toward EasyFeature.enabled?. It delegates to EasyFeatureLegacy and follows the old EASY_FEATURE_*_ACTIVE naming convention.
Use it only when you migrate existing flags. New work must register a feature and call enabled?.
module MyLegacyEngine
class << self
def my_feature_active?
EasyFeature.active?("EASY_FEATURE_MY_FEATURE_ACTIVE")
end
end
end
When you finally convert, swap the helper to enabled?, add the registry entry, and remove the ENV variable gate.