Ship behind a flag in five steps.
- Create a free workspace and open Flags.
- Create a stable key such as
checkout_v2. - Open Settings, generate a key for Development, and copy it immediately.
- Add the
togglefleetgem and configure the key. - Call
ToggleFleet.enabled?around the code path you want to control.
ToggleFleet stores a SHA-256 hash and a display prefix, not the full credential. Generate a separate key for each environment.
Generate one server credential per environment.
Go to Settings → SDK keys and connections. Select Generate new key for Development and copy the full value from the one-time reveal.
TOGGLEFLEET_SDK_KEY=tf_live_…The key grants read access to one environment's complete flag configuration and server-side evaluation endpoint. Keep it out of browser code, source control, logs, screenshots, and support tickets.
Rotate an exposed key
Generate a new key in Settings. Rotation invalidates the previous key immediately. Update the application secret, deploy it, and confirm the environment's Last connected time changes.
Install and configure the gem.
The open-source gem is published on RubyGems as togglefleet and licensed under MIT.
gem "togglefleet", "~> 0.2"
ToggleFleet.configure do |config| config.sdk_key = ENV.fetch("TOGGLEFLEET_SDK_KEY") config.refresh_interval = 15 # background refresh seconds config.default = false # fail-safe for unknown flags config.open_timeout = 3 config.read_timeout = 5 end ToggleFleet.start
Then evaluate anywhere in the process:
if ToggleFleet.enabled?(:checkout_v2, actor: current_user) render "checkout/v2" else render "checkout/current" end
enabled?.The check uses the latest configuration held in memory. *Normal local execution time still applies.
A flag is on when any gate matches.
Gate state is isolated by environment. Boolean is evaluated first, followed by actor, group, percentage of actors, and percentage of time.
| Gate | Dashboard value | Behavior |
|---|---|---|
| Boolean | On or off | On for every evaluation when enabled. |
| Actor | Comma-separated IDs | On for listed stable actor identifiers. |
| Group | Comma-separated names | On when a group supplied or resolved in your app matches. |
| % of actors | 0–100 | Deterministic per flag and actor; suitable for gradual rollouts. |
| % of time | 0–100 | Random per evaluation; useful for sampling, not sticky cohorts. |
Stable IDs in. Stable rollout out.
The Ruby SDK derives an actor ID in this order:
actor.togglefleet_idwhen definedactor.idwhen available, including ActiveRecord models- The string value of the actor itself
ToggleFleet.enabled?(:beta, actor: current_user) ToggleFleet.enabled?(:beta, actor: "account_42") ToggleFleet.enabled?(:beta) # boolean and % time gates only
Register group predicates
Group membership stays in your application; ToggleFleet stores only the group names enabled for a flag.
ToggleFleet.register_group(:admins) { |user| user.admin? } ToggleFleet.register_group(:internal) do |user| user.email.end_with?("@yourco.com") end ToggleFleet.enabled?(:beta, actor: current_user) ToggleFleet.enabled?(:eu_pricing, actor: user, groups: [:eu])
Resolve every flag
ToggleFleet.all(actor: current_user)
# => { "checkout_v2" => true, "billing_portal" => false }Two server-side JSON endpoints.
Use an environment SDK key as an exact Bearer credential. These endpoints intentionally do not enable browser CORS: exposing an SDK key to frontend JavaScript would grant anyone with that key access to the complete environment configuration. REST traffic is limited to 600 requests per minute per client IP; use /v1/config plus local evaluation for high-volume checks.
GET /v1/evaluate
Evaluate one flag on the server. Pass comma-separated groups when group targeting is required.
curl https://togglefleet.com/v1/evaluate \ -H "Authorization: Bearer $TOGGLEFLEET_SDK_KEY" \ -G --data-urlencode "flag=checkout_v2" \ --data-urlencode "actor=account_42" \ --data-urlencode "groups=beta,paid" # { "flag": "checkout_v2", "enabled": true }
GET /v1/config
Fetch the complete environment for local caching. The response includes an ETag. Send it back as If-None-Match; unchanged configuration returns HTTP 304 with no response body.
curl -i https://togglefleet.com/v1/config \ -H "Authorization: Bearer $TOGGLEFLEET_SDK_KEY" # HTTP/2 200 # etag: "7f…" # { "flags": { "checkout_v2": { … } } } curl -i https://togglefleet.com/v1/config \ -H "Authorization: Bearer $TOGGLEFLEET_SDK_KEY" \ -H 'If-None-Match: "7f…"' # HTTP/2 304
| Status | Meaning |
|---|---|
| 200 | Valid evaluation or configuration response. |
| 304 | Configuration is unchanged for the supplied ETag. |
| 400 | Missing or invalid flag key. |
| 401 | Missing, malformed, rotated, or unknown SDK key. |
| 404 | The requested flag does not exist in this workspace. |
| 429 | Rate limit reached; back off before retrying. |
| 500 | Unexpected service error; continue using last-good local state. |
Keep Development, Staging, and Production independent.
Each environment has its own SDK key and complete set of flag states. A newly created workspace starts with Development, Staging, and Production; generate each key only when you are ready to connect that environment.
Promote a tested state
On the Flags page, select the destination environment and use Copy states. This overwrites all destination gate values with the source environment's current values and records the operation in history.
It copies every flag state into the destination. Review both environments first and use change history if a rollback is required afterward.
Use multiple environments in one process
prod_config = ToggleFleet::Configuration.new.tap do |config| config.sdk_key = ENV.fetch("PROD_TOGGLEFLEET_KEY") end prod = ToggleFleet::Client.new(prod_config).start
Every flag-state change keeps its prior value.
The History page records the operator, timestamp, environment, action, and summary for flag, environment, key, membership, and workspace operations.
Flag-state updates are restorable. Select Rollback beside a restorable entry to put the flag back into the state captured immediately before that change. The rollback itself creates another history event.
Connected SDKs receive the restored state on their next background refresh. Use a safe rollout and verify production behavior after restoration.
Design the application to keep deciding.
- Local evaluation:
enabled?reads in-process state. - Conditional refresh: ETags turn unchanged polls into HTTP 304 responses.
- Last-good state: a failed refresh does not erase the previous configuration.
- Fail-safe default: before the first successful load, unknown flags return
config.default. - Bounded network calls: open and read timeouts are configurable.
- Instrumentation: attach
config.on_evaluationfor your own metrics or logging.
ToggleFleet.configure do |config| config.sdk_key = ENV.fetch("TOGGLEFLEET_SDK_KEY") config.on_evaluation = ->(flag, actor, result) { StatsD.increment("feature_flag.#{flag}.#{result}") } end
Treat a flag service as production infrastructure.
- Use a different SDK key for each environment.
- Keep keys in a server-side secret manager or protected environment variable.
- Never expose keys to browser or mobile application bundles.
- Rotate a key immediately if it enters a log, commit, screenshot, or ticket.
- Invite teammates through verified identity-provider email addresses.
- Use percentage rollouts and non-critical flags for the first integration.
- Review History after environment copy, key rotation, and production flag changes.