Skip to main content

Configuration

Configure one client at process startup. Core Toggly::Config and Toggly::Rails::Configuration expose different option sets; merge the relevant settings into one startup path.

Core Configuration Options​

OptionTypeDefaultDescription
app_keyString-Your Toggly app key (required unless offline)
environmentString"Production"Environment name
base_urlString"https://definitions.toggly.io/"Definitions API base URL
definitions_urlStringnilBase prefix override; endpoint path is appended
refresh_intervalInteger300Refresh interval in seconds
http_timeoutInteger10HTTP request timeout in seconds
enable_undefined_in_devBooleanfalseEnable unknown features in development
disable_background_refreshBooleanfalseDisable polling and WebSocket startup; initial fetch still runs
enable_live_updatesBooleantrueWebSocket live updates (needs websocket-client-simple)
use_signed_definitionsBooleanfalseFetch from /definitions-signed/...
allowed_key_idsArray<String>[]Accepted but unused; no local signature verification
defaultsHash{}Default feature values for offline mode
snapshot_providerObjectnilPersistence provider for caching
loggerLoggernilLogger instance for debugging
disable_entity_context_registrationBooleanfalseSkip startup schema upload; local entity mapping still works
app_version / instance_nameStringnilApplication/instance metadata

Client Configuration​

Basic Configuration​

client = Toggly::Client.new(
app_key: 'your-app-key',
environment: 'Production'
)

Full Configuration​

require 'logger'
client = Toggly::Client.new(
app_key: ENV['TOGGLY_APP_KEY'],
environment: 'Production',
base_url: 'https://definitions.toggly.io/',
refresh_interval: 60,
http_timeout: 5,
enable_live_updates: true,
use_signed_definitions: true,
enable_undefined_in_dev: false,
defaults: {
'critical-feature' => true,
'experimental-feature' => false
},
logger: Logger.new($stdout)
)

Using Config Object​

config = Toggly::Config.new(
app_key: 'your-app-key',
environment: 'Production',
refresh_interval: 120
)

client = Toggly::Client.new(config)

Signed definitions​

See Signed definitions for the signed endpoint and Rails options.

Feature Variants​

The Ruby SDK assigns variants locally from the definitions catalog (variants + allocation). There is no enable_variants toggle and no evaluated-variants-signed rail. Requires Ruby gem 1.1+ for Config#identity / set_identity.

Prefer ambient identity: config, set_identity, or Rails feature_variant (uses toggly_context). Per-call context: is an override.

require 'toggly'

client = Toggly::Client.new(
app_key: ENV['TOGGLY_APP_KEY'],
environment: 'Production',
identity: 'user-123' # optional default targeting userId
)
client.set_identity('user-123') # optional runtime update

client.enabled?('checkout-flow') # Local filter evaluation

variant = client.get_variant('checkout-flow')
if variant
puts variant.name # e.g. "treatment"
puts variant.configuration_value # Feature-specific payload, or nil
end

client.get_variant_value('checkout-flow')

# Override only when needed (e.g. impersonation):
client.get_variant(
'checkout-flow',
context: Toggly::Context.new(identity: 'other-user', groups: ['beta'])
)

client.close

In Rails, after the controller concern caches toggly_context:

variant = feature_variant(:checkout_flow)
value = feature_variant_value(:checkout_flow)

get_variant / feature_variant return nil when the feature key is unknown, has no catalog variants, or no allocation match. They do not raise for missing keys.

Do not confuse this with the variant: telemetry label. record_usage / record_view accept a variant: keyword that is a free-form usage tag (defaults to "enabled"/"disabled") — it does not assign a feature variant.

Live updates (WebSockets)​

See Live updates. Shared protocol: WebSocket sync. Reliability notes: Server-side reliability.

Rails Configuration​

Basic Setup​

config/initializers/toggly.rb
Toggly::Rails.configure do |config|
config.app_key = Rails.application.credentials.dig(:toggly, :app_key)
config.environment = Rails.env.production? ? 'Production' : 'Staging'
config.defaults = { 'ExpressCheckout' => false, 'new_dashboard' => false }
end

Rails-Specific Options​

OptionTypeDefaultDescription
use_signed_definitionsBooleanfalseFetch signed definitions endpoint
allowed_key_idsArray<String>[]Accepted but unused
request_context_enabledBooleantrueEnable automatic request context
identity_methodSymbol:idMethod to call on current_user for identity
groups_methodSymbolnilMethod to call on current_user for groups
context_builderProcnilCustom context builder
use_rails_cacheBooleanfalseUse Rails.cache for snapshots
cache_key_prefixString"toggly"Cache key prefix

Full Rails Configuration​

config/initializers/toggly.rb
Toggly::Rails.configure do |config|
# Core settings
config.app_key = Rails.application.credentials.dig(:toggly, :app_key)
config.environment = Rails.env.production? ? 'Production' : 'Staging'
config.refresh_interval = 60
config.use_signed_definitions = true

# User context
config.identity_method = :id
config.groups_method = :role_names

# Custom traits
config.add_trait(:plan) { |request, user| user&.subscription&.plan }

# Caching
config.use_rails_cache = true
config.cache_key_prefix = "shop:#{config.environment}:toggly"

# Development settings
config.enable_undefined_in_dev = Rails.env.development?
config.disable_background_refresh = Rails.env.test?

# Defaults for offline resilience
config.defaults = {
'critical-feature' => true
}
end

Custom Context Builder​

Use the complete request builder inside the same initializer. Default Rails mapping produces identity, groups, traits and entity; it does not populate claims or structured request. A country trait does not feed the Country filter.

The Rails adapter forwards app_key, environment, base_url, definitions_url, refresh_interval, http_timeout, enable_undefined_in_dev, disable_background_refresh, app_version, instance_name, defaults, snapshot_provider, use_signed_definitions and allowed_key_ids. It supplies Rails.logger automatically. It has no logger, telemetry, enable_live_updates or disable_entity_context_registration setters. Use the single-client core-options recipe for those settings.

Environment Variables​

You can use environment variables for sensitive values:

Toggly::Rails.configure do |config|
config.app_key = ENV.fetch('TOGGLY_APP_KEY')
config.environment = ENV.fetch('TOGGLY_ENVIRONMENT', 'Production')
config.base_url = ENV.fetch('TOGGLY_BASE_URL', 'https://definitions.toggly.io/')
end

Self-Hosted Toggly​

Set these on your startup configuration. Both URL options are base prefixes, not complete JSON URLs: the SDK appends definitions/{appKey}/{environment} (or definitions-signed/...).

For self-hosted installations:

config.base_url = 'https://toggly.yourcompany.com/'
# Or use a CDN for definitions
config.definitions_url = 'https://cdn.yourcompany.com/toggly/'

Logging​

The Rails adapter uses Rails.logger. For a core client, set a logger before construction:

require 'toggly'
require 'logger'
config = Toggly::Config.new(defaults: { 'ExpressCheckout' => false })
config.logger = Logger.new($stdout)
client = Toggly::Client.new(config)
client.close

Usage and metrics​

Core optionDefaultPurpose
enable_usage_tracking / enable_metricsSee belowEnable usage or metric batching
metrics_base_urlhttps://app.toggly.io/Default telemetry service
usage_flush_interval / metrics_flush_interval60.0 secondsBatch flush intervals
usage_client / metrics_clientnilOptional transports implementing send_stats / send_metrics

When app_key is passed to Config.new or Client.new, telemetry defaults on unless TOGGLY_DISABLE_TELEMETRY=1. Block configuration (Toggly.configure) and the Rails adapter first construct an empty core Config: assigning a key later does not recalculate these defaults. Set the two enable options explicitly on the core Config when using that path. Telemetry requires an app key; TOGGLY_DISABLE_TELEMETRY=1 disables it regardless of these options. Install grpc and google-protobuf for the default senders.

Inside request handling, after constructing that request's context and using the configured shared client:

if client.enabled?('ExpressCheckout', context: context)
# Call at the actual display and interaction points in your app.
client.record_view('ExpressCheckout', identity: context.identity)
client.record_usage('ExpressCheckout', identity: context.identity)
client.measure('checkout_total', 149.95, feature: 'ExpressCheckout', variant: 'enabled')
client.increment_counter('orders', 1, feature: 'ExpressCheckout', variant: 'enabled')
client.observe('checkout_ms', 85, feature: 'ExpressCheckout', variant: 'enabled')
end
# Normally batched automatically; useful at a controlled flush boundary.
client.flush_telemetry

enabled? records checks automatically. A view means displayed UI; usage means an interaction, so do not record both merely because you checked a flag. measure sums values in the flush window, increment_counter adds counts, and observe records individual observations. variant is a telemetry label, not a variant assignment API. Close the client at shutdown to stop its workers and flush pending telemetry.