RepoPilotOpen in app β†’

flippercloud/flipper

🐬 Beautiful, performant feature flags for Ruby.

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained β€” safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI β€” clean foundation to fork and modify.

Learn fromHealthy

Documented and popular β€” useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture β€” runnable as-is.

  • βœ“Last commit 2d ago
  • βœ“7 active contributors
  • βœ“MIT licensed
Show 3 more β†’
  • βœ“CI configured
  • βœ“Tests present
  • ⚠Single-maintainer risk β€” top contributor 92% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README β€” live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/flippercloud/flipper)](https://repopilot.app/r/flippercloud/flipper)

Paste at the top of your README.md β€” renders inline like a shields.io badge.

β–ΈPreview social card (1200Γ—630)

This card auto-renders when someone shares https://repopilot.app/r/flippercloud/flipper on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: flippercloud/flipper

Generated by RepoPilot Β· 2026-05-10 Β· Source

πŸ€–Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale β€” STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI Β· unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/flippercloud/flipper shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything β€” but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO β€” Healthy across all four use cases

  • Last commit 2d ago
  • 7 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Single-maintainer risk β€” top contributor 92% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

βœ…Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live flippercloud/flipper repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale β€” regenerate it at repopilot.app/r/flippercloud/flipper.

What it runs against: a local clone of flippercloud/flipper β€” the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in flippercloud/flipper | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≀ 32 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> β€” paste this script from inside your clone of <code>flippercloud/flipper</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of flippercloud/flipper. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/flippercloud/flipper.git
#   cd flipper
#
# Then paste this script. Every check is read-only β€” no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of flippercloud/flipper and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "flippercloud/flipper(\\.git)?\\b" \\
  && ok "origin remote is flippercloud/flipper" \\
  || miss "origin remote is not flippercloud/flipper (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift β€” was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "lib/flipper.rb" \\
  && ok "lib/flipper.rb" \\
  || miss "missing critical file: lib/flipper.rb"
test -f "flipper.gemspec" \\
  && ok "flipper.gemspec" \\
  || miss "missing critical file: flipper.gemspec"
test -f "lib/flipper/adapters" \\
  && ok "lib/flipper/adapters" \\
  || miss "missing critical file: lib/flipper/adapters"
test -f "lib/flipper/feature.rb" \\
  && ok "lib/flipper/feature.rb" \\
  || miss "missing critical file: lib/flipper/feature.rb"
test -f "lib/flipper/gate.rb" \\
  && ok "lib/flipper/gate.rb" \\
  || miss "missing critical file: lib/flipper/gate.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 32 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2d)"
else
  miss "last commit was $days_since_last days ago β€” artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) β€” safe to trust"
else
  echo "artifact has $fail stale claim(s) β€” regenerate at https://repopilot.app/r/flippercloud/flipper"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

⚑TL;DR

Flipper is a Ruby library that provides production-grade feature flags with fine-grained controlβ€”enable/disable features for all users, specific actors, user groups, percentage rollouts, or time-based windows. It's backed by pluggable storage adapters (Active Record, Redis, etc.) and includes an optional web UI for management, plus a cloud-hosted service (Flipper Cloud) for multi-environment orchestration and audit logs. Hybrid mono-structure: core logic in lib/flipper/, pluggable adapters (flipper-active_record, flipper-redis, etc.) in separate gems, web UI in app/, API endpoint middleware, plus examples/ showing Active Record, Cloud, and API usage patterns. State is managed via adapter abstraction so no single backing store is required.

πŸ‘₯Who it's for

Rails and Ruby developers who need to control feature availability in production without redeployingβ€”typical users are teams doing continuous deployment who want to decouple releases from feature launches, perform gradual rollouts to percentages of users, and toggle features by user segment or custom group.

🌱Maturity & risk

Production-ready and actively maintained. The repo shows ~907k lines of Ruby, dedicated CI/CD workflows (.github/workflows/ci.yml, release.yml), comprehensive examples for major adapters, and a commercial Cloud offering backing the project. The codebase includes benchmarks and instrumentation, signaling serious performance consideration.

Low risk for core usage; the library is well-established with multiple storage adapter options reducing lock-in. However, the Cloud service is a proprietary upsell, so self-hosted-only teams depend on the open-source adapters. No obvious red flags in commit recency or test gaps visible from the file structure.

Active areas of work

Active development indicated by CI/CD workflows and example updates. The repo includes examples for Cloud polling intervals, group migration patterns, and both memoized and non-memoized API setups, suggesting recent iteration on performance and flexibility.

πŸš€Get running

git clone https://github.com/flippercloud/flipper.git && cd flipper && bundle install && bundle exec rspec to run the test suite. For interactive exploration: ruby examples/basic.rb or examples/active_record/basic.rb with database setup.

Daily commands: bundle exec rake to run full test suite. For examples: cd examples/active_record && ruby basic.rb (requires database); cd examples/api && rackup basic.ru starts the API server on port 9292. Docker option: docker-compose up for containerized development.

πŸ—ΊοΈMap of the codebase

  • lib/flipper.rb β€” Core entry point and DSL for the entire Flipper feature flag system; every integration starts here.
  • flipper.gemspec β€” Primary gem specification defining dependencies, version, and core package metadata for Flipper.
  • lib/flipper/adapters β€” Adapter abstraction layer enabling pluggable storage backends (Redis, Mongo, ActiveRecord, etc.).
  • lib/flipper/feature.rb β€” Central Feature class modeling feature flags and their evaluation logic against actors and constraints.
  • lib/flipper/gate.rb β€” Gate abstraction defining how features are enabled/disabled (boolean, group, actor, percentage).
  • flipper-ui.gemspec β€” Separate UI gem enabling the web dashboard; critical for understanding the admin interface architecture.

πŸ› οΈHow to make changes

Add a new storage adapter

  1. Create a new gem file at flipper-{adapter_name}.gemspec following the pattern in flipper-redis.gemspec (flipper-redis.gemspec)
  2. Implement adapter class inheriting from Flipper::Adapter::Memory, implementing get/set/delete for feature state (lib/flipper/adapters)
  3. Add initialization example in examples/{adapter_name}/basic.rb showing adapter instantiation and Flipper.wrap() usage (examples/redis/basic.rb)
  4. Update .github/workflows/ci.yml to test the new adapter in the build matrix (.github/workflows/ci.yml)

Add a new gate type (constraint logic)

  1. Create new gate class in lib/flipper/gates/{gate_name}.rb inheriting from Flipper::Gate (lib/flipper/gate.rb)
  2. Implement required methods: name, description, and execute(feature, thing) for evaluation logic (lib/flipper/gate.rb)
  3. Register gate in Flipper::Feature#gates or adapter initialization (lib/flipper/feature.rb)
  4. Add usage example in examples/{gate_name}.rb demonstrating the new constraint type (examples/dsl.rb)

Integrate Flipper into a Rails application

  1. Add gem 'flipper' and chosen adapter (gem 'flipper-redis') to Gemfile (flipper.gemspec)
  2. Create config/initializers/flipper.rb to instantiate Flipper with your adapter and memoization layer (examples/active_record/basic.rb)
  3. Mount flipper UI in config/routes.rb: mount Flipper::UI::Engine => '/admin/flags' (requires flipper-ui gem) (examples/ui/basic.ru)
  4. Use Flipper.enabled?(:feature_name, actor) in controllers/helpers to gate feature code paths (examples/enabled_for_actor.rb)

Add custom group membership logic

  1. Define custom group in Flipper.register_group(:group_name) { |actor| boolean_check } (examples/group_dynamic_lookup.rb)
  2. Call feature.enable_group(:group_name) to apply the group gate to a feature (examples/group.rb)
  3. Test with Flipper.enabled?(:feature_name, actor) where actor matches group membership criteria (examples/group_with_members.rb)

πŸ”§Why these technologies

  • Ruby/Rails β€” Native DSL for feature flags with deep Rails integration; leverage Ruby's metaprogramming for elegant gate definitions
  • Multiple adapters (Redis, Mongo, ActiveRecord, Sequel) β€” No vendor lock-in; teams choose storage backend matching their existing infrastructure
  • Rack-based UI β€” Framework-agnostic web dashboard mountable in any Rack app; minimal dependencies
  • Memoization layer (optional caching) β€” Reduce latency and storage hits by caching feature state per-request or in-memory; critical for performance at scale

βš–οΈTrade-offs already made

  • Pluggable adapter architecture vs. single canonical store

    • Why: Maximize flexibility across heterogeneous app stacks; teams use different databases
    • Consequence: Added complexity; adapter interface must be stable and minimal; more testing surface area
  • Memoization as optional middleware vs. built-in

    • Why: Allow opt-in performance optimization without forcing caching complexity on all users
    • Consequence: Default behavior slower if cache not configured; requires user awareness of perf implications
  • Separate gems per adapter/feature (flipper-redis, flipper-ui, flipper-api, flipper-cloud)

    • Why: Reduce dependency footprint; users only install what they need
    • Consequence: More repos to maintain; version coordination required; onboarding more complex
  • Percentage gates use deterministic hashing vs. random sampling

    • Why: Consistent rollout experience across requests; same user always in/out of percentage-based flag
    • Consequence: Cannot dynamically adjust percentage mid-rollout without recalculating all users

🚫Non-goals (don't propose these)

  • Real-time feature flag updates across all processes without polling or webhooks
  • Built-in analytics or usage tracking of flag evaluations
  • A/B testing statistical analysis or experimentation framework
  • Browser/client-side feature flag evaluation without server roundtrip
  • Cross-language SDK (Go, Node, Python, etc.); Ruby-only library

πŸͺ€Traps & gotchas

Adapters must implement the Adapter interface fully or memoization may silently cache stale data; the Active Record adapter requires the flipper_features table migration (included in flipper-active_record gem). Cloud examples assume valid API token in ENV['FLIPPER_TOKEN']. Web UI defaults to port 5000; RackUp examples use 9292. Memoization is per-request by default but persists across code pathsβ€”understand the memoization scope in your framework.

πŸ—οΈArchitecture

πŸ’‘Concepts to learn

  • Feature Flag / Feature Toggle β€” Core abstraction of this project; understanding the toggle lifecycle (enabled, actor, group, percentage) is essential to using Flipper correctly
  • Adapter Pattern β€” Flipper's pluggable storage backends (Active Record, Redis, Memory, Cloud) all implement the Adapter interface; critical for understanding how to add a new storage backend or switch between them
  • Memoization / Caching β€” Flipper's in-memory memoization (per-request caching) is crucial for performance in production; misunderstanding its scope can lead to stale flag reads or memory leaks
  • Percentage-based Rollout / Consistent Hashing β€” Enabling a feature for X% of actors requires deterministic bucketing so the same actor always gets the same result; Flipper uses a hash-based approach to ensure consistency
  • Actor Abstraction β€” Any object (user, org, request) can be an actor; Flipper uses duck typing (id method) to bucket actors, allowing flexible grouping logic beyond just user IDs
  • Instrument/Instrumentation Hooks β€” Flipper emits instrumentation events (cache hits, adapter calls) for observability; understanding the events and their payloads is essential for monitoring and debugging performance
  • Backoff Policy / Exponential Backoff β€” Cloud variant uses configurable backoff when polling for flag updates (see examples/cloud/backoff_policy.rb); critical for reducing load on the Cloud API in distributed systems
  • jnunemaker/rollout β€” Predecessor feature flag gem for Ruby; simpler but less flexible, now largely superseded by Flipper
  • ruby-kafka/ruby-kafka β€” Not directly related but used by some Flipper deployments for streaming audit/analytics events from Cloud to data warehouses
  • rails/rails β€” Flipper integrates deeply with Rails via Active Record adapter and Railtie hooks; understanding Rails app structure is essential
  • flippercloud/flipper-ui β€” Companion UI component library (if separate); check for standalone web dashboard repos under flippercloud org
  • redis/redis-rb β€” Storage adapter for Flipper; many deployments use flipper-redis for high-performance flag evaluation without a database query

πŸͺ„PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add integration tests for MongoDB adapter in CI pipeline

The repo has examples/mongo/ demonstrating MongoDB support, but there's no dedicated CI workflow for testing the MongoDB adapter. Currently, .github/workflows/ only shows ci.yml, examples.yml, and release.yml. Adding a MongoDB integration test workflow would catch adapter regressions and ensure consistency with other adapters (Active Record, etc.). This is particularly valuable since data store consistency is a core feature claim in the README.

  • [ ] Create .github/workflows/mongo-integration.yml similar to existing CI patterns
  • [ ] Add MongoDB service container configuration using GitHub Actions services
  • [ ] Reference examples/mongo/basic.rb and examples/mongo/internals.rb as test targets
  • [ ] Ensure test matrix covers relevant Ruby versions from existing ci.yml
  • [ ] Update docs/README.md or create docs/MongoCI.md documenting the new workflow

Add comprehensive benchmarking CI workflow and results tracking

The repo contains benchmark/ directory with IPS benchmarks for various subsystems (active_record, instrumentation, typecast, enabled checks), but no automated benchmarking workflow. This means performance regressions could slip through undetected. Adding a benchmarking workflow would track performance metrics over time and alert maintainers to unexpected changes, which is critical given the 'performant' claim in the README.

  • [ ] Create .github/workflows/benchmark.yml that runs benchmark/*.rb files on each push
  • [ ] Configure the workflow to store/compare baseline results (consider using benchmark/results or similar artifact storage)
  • [ ] Add output parsing from benchmark IPS results to create human-readable reports
  • [ ] Consider integrating with comment-on-PR actions to show before/after comparisons
  • [ ] Document expected baseline values in docs/Benchmarking.md

Add missing test coverage for cloud adapter polling and backoff strategies

The examples/cloud/ directory shows advanced features like poll_interval/ configuration and backoff_policy.rb, but these are only documented as examples, not tested in the main test suite. Given that Flipper Cloud is a core product offering, ensuring robust test coverage for cloud-specific features (threaded polling, forked process handling, backoff strategies) would prevent critical bugs in the cloud adapter.

  • [ ] Identify spec files for cloud adapter (likely spec/flipper/cloud/ or similar)
  • [ ] Add unit tests for CloudConfig poll_interval settings (reference examples/cloud/poll_interval/)
  • [ ] Add tests for backoff policy behavior under various network failure scenarios (reference examples/cloud/backoff_policy.rb)
  • [ ] Add integration tests for forked process handling (reference examples/cloud/forked.rb)
  • [ ] Add tests for threaded polling to ensure thread safety (reference examples/cloud/threaded.rb)
  • [ ] Run full test suite to ensure no regressions

🌿Good first issues

  • Add a new gate type (e.g., 'time_window' gate) with tests in spec/flipper/gate.rb and examples in examples/; involves modifying lib/flipper/gate.rb and updating the adapter interface
  • Expand Active Record adapter benchmarks in benchmark/active_record_ips.rb to include newer Ruby versions and compare against Redis adapterβ€”requires running local benchmarks and documenting results
  • Document the adapter contract in a new docs/adapters/custom.md file showing the exact methods required by Adapter base class, using lib/flipper/adapters/memory.rb as the reference implementation

⭐Top contributors

Click to expand

πŸ“Recent commits

Click to expand
  • bf47515 β€” Merge pull request #989 from flippercloud/review-pr-988 (jnunemaker)
  • 3dd5d7c β€” Enforce read-only mode on import action (jnunemaker)
  • be741de β€” Merge pull request #986 from pkrisko/feat/add-version-check-enabled-config (jnunemaker)
  • bc8e58d β€” Bump version to 1.4.1 (jnunemaker)
  • 5e9e096 β€” Merge pull request #987 from flippercloud/claude/youthful-hugle (jnunemaker)
  • 603b770 β€” Skip ETag header on cache_bust to prevent stale webhook syncs (jnunemaker)
  • d17bc3b β€” Add version_check_enabled config to skip version.js in UI (pkrisko)
  • 7f4daa5 β€” Merge pull request #982 from flippercloud/strict-adapter-sync-mode (jnunemaker)
  • 7621476 β€” Add sync mode bypass to Strict adapter (jnunemaker)
  • 7e6ce79 β€” Note to purge release URLs after releasing (jnunemaker)

πŸ”’Security observations

The Flipper repository

  • High Β· Outdated Ruby Base Image β€” Dockerfile. Dockerfile uses Ruby 3.0 which reached end-of-life on 2022-12-25. This image no longer receives security patches and may contain known vulnerabilities in the Ruby runtime and included dependencies. Fix: Update to a currently supported Ruby version (3.2 or 3.3 LTS). Use 'FROM ruby:3.3-slim' or newer to reduce attack surface and receive security updates.
  • High Β· Outdated Docker Base Images in docker-compose.yml β€” docker-compose.yml. Multiple service images use pinned but outdated versions: Redis 6.2.5 (EOL 2022-04-30), MongoDB 4.4.8 (EOL 2022-02-11), and Memcached 1.4.33 (ancient). These versions contain known security vulnerabilities and will not receive patches. Fix: Update to current supported versions: redis:7-alpine, mongo:6.0 or 7.0, memcached:1.6-alpine. Use alpine variants to reduce image size and attack surface.
  • Medium Β· Missing Docker Security Options β€” docker-compose.yml. The docker-compose.yml configuration lacks security constraints such as resource limits, read-only filesystems, non-root users, and security_opt settings. This allows potential container escape and resource exhaustion attacks. Fix: Add security configurations: set memory limits, use 'security_opt: [no-new-privileges=true]', run containers as non-root users, and implement resource constraints (cpu_shares, mem_limit).
  • Medium Β· Unencrypted Inter-Service Communication β€” docker-compose.yml. Docker-compose services communicate without TLS/encryption. Redis, MongoDB, and Memcached connections in 'links' section use plain text protocols vulnerable to man-in-the-middle attacks. Fix: Enable TLS for Redis, MongoDB, and Memcached. Use 'networks' instead of deprecated 'links'. Implement authentication credentials for all services.
  • Medium Β· Incomplete Dependency Vulnerability Scanning β€” package.json. The package.json contains @popperjs/core ^2.11.8 and bootstrap ^5.3.3 with permissive caret versioning. No lock file (package-lock.json or yarn.lock) is visible, allowing non-deterministic builds and potential dependency confusion attacks. Fix: Use package-lock.json or yarn.lock to pin exact dependency versions. Implement automated dependency scanning with npm audit or Dependabot. Consider stricter version constraints.
  • Low Β· Commented Dependencies in Dockerfile β€” Dockerfile. Dockerfile contains commented-out dependencies (libpq-dev, libxml2-dev, etc.) that may indicate incomplete security hardening or unclear deployment requirements. Fix: Remove commented-out code or document why dependencies are optional. Clearly specify production dependencies only. Use build arguments for optional features.
  • Low Β· Debug Tools in Production Image β€” Dockerfile. Dockerfile includes 'vim' installation which is unnecessary for production and increases image surface area and attack vectors. Fix: Remove vim from the production image. Use multi-stage builds if debugging tools are needed for development. Install only essential packages.
  • Low Β· Missing HEALTHCHECK in Dockerfile β€” Dockerfile. Dockerfile does not define HEALTHCHECK instruction, making it difficult to detect container failures and potentially allow unhealthy containers to remain running. Fix: Add HEALTHCHECK instruction to verify application availability. For Rails app, check /health or similar endpoint with appropriate timeout and retry settings.
  • Low Β· Deprecated docker-compose v2.4 Syntax β€” docker-compose.yml. docker-compose.yml uses version 2.4 which is deprecated. Modern deployments should use version 3.8+ for better security features and active maintenance. Fix: Upgrade to 'version: "3.8"' or higher. Review and leverage newer security features like secrets management and health checks.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals β€” see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals Β· flippercloud/flipper β€” RepoPilot