Featureflip Ruby SDK
Ruby SDK for Featureflip - evaluate feature flags locally with near-zero latency.
Installation
Add to your Gemfile:
gem "featureflip"Or install directly:
gem install featureflipQuick Start
require "featureflip"
# Initialize the client (blocks until flags are loaded)
client = Featureflip::Client.get("your-sdk-key")
# Evaluate a feature flag
enabled = client.bool_variation("my-feature", { "user_id" => "user-123" }, false)
if enabled
puts "Feature is enabled!"
else
puts "Feature is disabled"
end
# Clean shutdown
client.closeConfiguration
config = Featureflip::Config.new(
base_url: "https://eval.featureflip.io", # Evaluation API URL (default)
streaming: true, # Use SSE for real-time updates (default)
poll_interval: 30, # Polling interval in seconds
send_events: true, # Enable analytics event tracking (default)
flush_interval: 30, # Event flush interval in seconds
flush_batch_size: 100, # Events per batch
init_timeout: 10, # Max seconds to wait for initialization
connect_timeout: 5, # HTTP connection timeout in seconds
read_timeout: 10, # HTTP read timeout in seconds
max_stream_retries: 5, # SSE retries before falling back to polling
)
client = Featureflip::Client.get("your-sdk-key", config: config)The SDK key can also be set via the FEATUREFLIP_SDK_KEY environment variable.
Singleton Convenience API
For applications that use a single client instance:
Featureflip.configure do |c|
c.sdk_key = "your-sdk-key"
c.base_url = "https://eval.featureflip.io"
c.streaming = true
end
enabled = Featureflip.bool_variation("my-feature", { "user_id" => "123" }, false)
# On shutdown
Featureflip.closeLifetime
Client.get returns handles backed by a shared core keyed by SDK key. Multiple calls with the same key share one set of connections and background threads:
client1 = Featureflip::Client.get("sdk-key")
client2 = Featureflip::Client.get("sdk-key")
# client1 and client2 share the same underlying resources
client1.close # Resources still alive — client2 holds a reference
client2.close # Now resources are cleaned upThis makes the SDK safe to use in dependency injection containers regardless of lifetime registration (singleton, scoped, or transient).
Evaluation
Context can use string or symbol keys:
context = { user_id: "123", email: "user@example.com" }
# or
context = { "user_id" => "123", "email" => "user@example.com" }
# Boolean flag
enabled = client.bool_variation("feature-key", context, false)
# String flag
tier = client.string_variation("pricing-tier", context, "free")
# Number flag
limit = client.number_variation("rate-limit", context, 100)
# JSON flag
config = client.json_variation("ui-config", context, { "theme" => "light" })Detailed Evaluation
detail = client.variation_detail("feature-key", { user_id: "123" }, false)
detail.value # The evaluated value
detail.reason # "RuleMatch", "Fallthrough", "FlagDisabled", "FlagNotFound"
detail.rule_id # Rule ID if reason is "RuleMatch"
detail.variation_key # Key of the matched variationEvent Tracking
# Track custom events
client.track("checkout-completed", { user_id: "123" }, { total: 99.99 })
# Identify users for segment building
client.identify({ user_id: "123", email: "user@example.com", plan: "pro" })
# Force flush pending events
client.flushTesting
Use the test client for deterministic unit tests with no network calls:
client = Featureflip::Client.for_testing(
"my-feature" => true,
"pricing-tier" => "pro"
)
client.bool_variation("my-feature", {}, false) # => true
client.string_variation("pricing-tier", {}, "free") # => "pro"
client.bool_variation("unknown", {}, false) # => false (default)Rails Setup
Featureflip is framework-agnostic. For Rails, initialize in an initializer:
# config/initializers/featureflip.rb
Featureflip.configure do |c|
c.sdk_key = ENV["FEATUREFLIP_SDK_KEY"]
c.streaming = true
end
# For Puma/Unicorn/Passenger — respawn threads after fork
# config/puma.rb
on_worker_boot do
Featureflip.restart
endFeatures
- Local evaluation - Near-zero latency after initialization
- Real-time updates - SSE streaming with automatic polling fallback
- Event tracking - Automatic batching and background flushing
-
Test support -
for_testingfactory for deterministic unit tests - Thread-safe - Mutex-protected flag store and event queue
-
Fork-safe -
restartmethod for Puma/Unicorn/Passenger worker processes -
Zero runtime dependencies - Uses only Ruby stdlib (
net/http,digest/md5)
Requirements
- Ruby 3.2+
Development
# Install dependencies
bundle install
# Run tests
bundle exec rspec
# Run specific test file
bundle exec rspec spec/featureflip/evaluation/evaluator_spec.rbLicense
Apache-2.0