{"id":19558550,"url":"https://github.com/jcagarcia/rollout-redis","last_synced_at":"2025-07-27T05:33:06.572Z","repository":{"id":203071171,"uuid":"708187603","full_name":"jcagarcia/rollout-redis","owner":"jcagarcia","description":"Easy and fast feature flags based on the latest Redis versions","archived":false,"fork":false,"pushed_at":"2023-10-28T14:42:36.000Z","size":77,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-11T21:34:01.357Z","etag":null,"topics":["degrade","fast","feature-flagging","feature-flags","feature-flippers","feature-switcher","feature-toggles","features","flipper","gem","hacktoberfest","rails","redis","redis-database","rollout","rollout-gem","ruby","ruby-gem","simple"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jcagarcia.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"patreon":"jcagarcia"}},"created_at":"2023-10-21T19:34:17.000Z","updated_at":"2024-01-18T07:03:04.000Z","dependencies_parsed_at":null,"dependency_job_id":"76ecc8e9-4751-463b-a74e-d2581461786a","html_url":"https://github.com/jcagarcia/rollout-redis","commit_stats":null,"previous_names":["jcagarcia/rollout-redis"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jcagarcia/rollout-redis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcagarcia%2Frollout-redis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcagarcia%2Frollout-redis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcagarcia%2Frollout-redis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcagarcia%2Frollout-redis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jcagarcia","download_url":"https://codeload.github.com/jcagarcia/rollout-redis/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcagarcia%2Frollout-redis/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267306764,"owners_count":24067035,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["degrade","fast","feature-flagging","feature-flags","feature-flippers","feature-switcher","feature-toggles","features","flipper","gem","hacktoberfest","rails","redis","redis-database","rollout","rollout-gem","ruby","ruby-gem","simple"],"created_at":"2024-11-11T04:47:25.711Z","updated_at":"2025-07-27T05:33:06.307Z","avatar_url":"https://github.com/jcagarcia.png","language":"Ruby","funding_links":["https://patreon.com/jcagarcia"],"categories":[],"sub_categories":[],"readme":"# rollout-redis ⛳️\n\n[![Gem Version](https://badge.fury.io/rb/rollout-redis.svg)](https://badge.fury.io/rb/rollout-redis)\n\nFast and easy feature flags based on Redis. \n\nBased on the discontinued [rollout](https://github.com/fetlife/rollout) project, removing some capabilities, including some new features and supporting latest Redis versions.\n\nTopics covered in this README:\n\n- [Install it](#install-it)\n- [Quick Start](#quick-start-)\n- [Advanced features](#advanced-features-)\n  - [Gradual activation based on percentages](#gradual-activation-based-on-percentages)\n  - [Caching Feature Flags](#caching-feature-flags)\n  - [Auto-deactivating flags](#auto-deactivating-flags)\n  - [Sending Notifications](#sending-notifications)\n- [Rake tasks](#rake-tasks)\n- [Migrating from rollout gem](#migrating-from-rollout-gem-)\n  - [Compatible payloads and keys](#compatible-payloads-and-keys)\n- [Changelog](#changelog)\n- [Contributing](#contributing)\n\n## Install it \n\n```bash\ngem install rollout-redis\n```\n\n## Quick Start 💨\n\nInstantiate the `Rollout` class sending a `Redis` instance as a parameter.\n\n```ruby\nrequire 'redis'\nrequire 'rollout'\n\n@redis ||= Redis.new(\n        host: ENV.fetch('REDIS_HOST'),\n        port: ENV.fetch('REDIS_PORT')\n      )\n@rollout ||= Rollout.new(@redis)\n```\n\nNow you can activate Feature Flags:\n\n```ruby\n@rollout.activate('FEATURE_FLAG_NAME') # =\u003e true/false\n```\n\nVerify if a feature is currently enabled:\n\n```ruby\nif @rollout.active?('FEATURE_FLAG_NAME')\n  # your new code here...\nend\n```\n\nAn alternative to the if check, is to wrap your code under the `with_feature` method. The wrapped code will be performed only if the feature flag is active:\n\n```ruby\n@rollout.with_feature('FEATURE_FLAG_NAME') do\n  # your new code here...\nend\n```\n\nIf there is an issue, you have the option to disable a feature:\n\n```ruby\n@rollout.deactivate('FEATURE_FLAG_NAME')\n```\n\nIf you want to list all the stored feature flags, you can use the `features` method:\n\n```ruby\n@rollout.features\n```\n\nThe response will be an array of hashes with all the information about the stored feature flags\n\n```ruby\n[\n  { name: 'a-feature-flag', percentage: 100, data: { requests: 50, errors: 1 } },\n  { name: 'another-feature-flag', percentage: 20, data: { requests: 1, errors: 0 } },\n  { name: 'super-feature-flag', percentage: 50, data: { requests: 828, errors: 34 } }\n]\n```\n\n## Advanced features 🦾\n\n### Gradual activation based on percentages\n\nWhen introducing a new feature, it's a recommended practice to gradually enable it for a specific portion of your target audience to evaluate its impact. To achieve this, you can utilize the `activate` method, as shown below:\n\n```ruby\n@rollout.activate('FEATURE_FLAG_NAME', 20)\n```\n\nNow, to know if a feature flags is enabled, you need to provide a determinator (in this example, we're using the user email):\n\n```ruby\nif @rollout.active?('FEATURE_FLAG_NAME', user_email)\n  # your new code here...\nend\n```\n\nThe gradual activation also works wrapping your code within the `with_feature` method, you just need to provde the determinator you want to use.\n\n```ruby\n@rollout.with_feature('FEATURE_FLAG_NAME', user_email) do\n  # your new code here...\nend\n```\n\nIt's important to note that if you use the `active?` method without specifying a determinator to determine whether this subset of the audience should see the new feature, it will always return `false` since the activation percentage is less than 100%. See:\n\n```ruby\n@rollout.activate('FEATURE_FLAG_NAME', 20)\n@rollout.active?('FEATURE_FLAG_NAME') # =\u003e false\n```\n\n### Caching Feature Flags\n\nThe Rollout gem is tightly integrated with Redis for feature flag status management. Consequently, occasional connectivity issues between your application and the Redis storage may arise.\n\nTo prevent potential application degradation when the Redis storage is unavailable, you can enable feature flag status caching during the gem's instantiation:\n\n```ruby\n@rollout ||= Rollout.new(redis).with_cache\n```\n\nAdditionally, you can specify extra parameters to configure the duration (in seconds) for which the feature flag status is stored in the cache. By default, this duration is set to 300 seconds (5 minutes):\n\n```ruby\n@rollout ||= Rollout.new(redis)\n              .with_cache(expires_in: 300)\n```\n\nIn the case that you need to clear the cache at any point, you can make use of the `clean_cache` method:\n\n```ruby\n@rollout.clean_cache\n```\n\n### Auto-deactivating flags\n\nIf you want to allow the gem to deactivate all the feature flags automatically when a threshold of errors is reached, you can enable the degrade feature using the `with_degrade` method.\n\n```ruby\n@rollout ||= Rollout.new(redis)\n              .with_cache\n              .with_degrade(min: 100, threshold: 0.1)\n```\n\nHowever, if you just want to activate the degradation of an specific feature flag, you need to provide the following information when activating the feature flag (note that now the percentage is a mandatory parameter if you want to pass the degrade options):\n\n```ruby\n@rollout.activate('FEATURE_FLAG_NAME', 100, degrade: { min: 500, threshold: 0.2 })\n```\n\nThe same configuration 👆 is available when using the rake task for activating the feature flag. Check [Rake tasks](#rake-tasks) section.\n\n```shell\nbundle exec rake rollout:on[FEATURE_FLAG_NAME,100,500,0.2]\n```\n\nSo now, instead of using the `active?` method, you need to wrap your new code under the `with_feature` method.\n\n```ruby\n@rollout.with_feature('FEATURE_FLAG_NAME') do\n  # your new feature code here...\nend\n```\n\nWhen any unexpected error appears during the wrapped code execution, the Rollout gem will take it into account for automatically degrading the feature flag if the threshold of errors is reached. The feature flag will not be removed from the redis, but it will change its percentage to 0 and it will be marked as degraded.\n\n_NOTE_: All the managed or captured errors inside the wrapped code will not be taken into consideration for degrading the feature flag.\n\n### Sending notifications\n\n`rollout-redis` gem can send different notifications to your development team. For enabling this feature, you just need to use the `with_notifications` instance method providing the channels where you want to publish each of the different events that can occur:\n\n- **status_change**: This notification is triggered when a feature flag is activated or deactivated using the `rollout-redis` gem.\n- **degrade**: This notification is triggered when a feature flag is automatically degraded because the threshold of errors is reached\n  - The instance must be configured for automatically degrading using the `with_degrade` instance method.\n\nYou must provide at least one [channel](#defining-the-channels) as a parameter if you want to enable the notifications for that specific event. If no channels provided, the notifications will not be sent. \n\n```ruby\n@rollout ||= Rollout.new(redis)\n              .with_cache\n              .with_degrade(min: 100, threshold: 0.1)\n              .with_notifications(\n                status_change: [slack_channel],\n                degrade: [slack_channel, email_channel]\n              )\n```\n\n#### Defining the channels\n\nWhen enabling a notification, you can provide the different channels where the notification should be published. `rollout-redis` gem offers different channels that can be configured.\n\n##### Slack Channel\n\nAllows you to send notifications using a slack webhook.\n\nThe first thing to do is to setup an incoming webhook service integration. You can do this from your services page.\n\nAfter that, you can provide the obtained webhook url when instantiating the Slack channel.\n\n```ruby\nrequire 'rollout'\n\nslack_channel = Rollout::Notifications::Channels::Slack.new(\n  webhook_url: ENV.fetch('SLACK_COMPANY_WEBHOOK_URL'),\n  channel: '#feature-flags-notifications',\n  username: 'rollout-redis'\n)\n```\n\n##### Email Channel\n\nAllows you to send notifications via email.\n\n```ruby\nrequire 'rollout'\n\nemail_channel = Rollout::Notifications::Channels::Email.new(\n  smtp_host: ENV.fetch('SMTP_HOST'),\n  smtp_port: ENV.fetch('SMTP_PORT'),\n  from: 'no-reply@rollout-redis.com',\n  to: 'developers@yourcompany.com'\n)\n```\n\n##### Custom channel\n\nIf you want to send the notifications using a different channel not offered by this gem, you can implement your own class with a `publish` method.\n\n```ruby\nrequire 'rollout'\n\nmodule YourApp\n  class YourCustomChannel\n    def initialize()\n      # provide here whatever you need for configuring your channel\n    end\n\n    def publish(text)\n      # Implement the way you want to publish the notification\n    end\n  end\nend\n```\n\nAfter implementing it, you can pass it to the list of configured channels\n\n```ruby\nyour_channel = YourApp::YourCustomChannel.new(url: 'wadus', param2: 'foo')\n@rollout ||= Rollout.new(redis)\n              .with_cache\n              .with_degrade(min: 100, threshold: 0.1)\n              .with_notifications(\n                status_change: [your_channel],\n                degrade: [your_channel]\n              )\n```\n\n## Rake tasks\n\nIn order to have access to the rollout rakes, you have to load manually the task definitions. For doing so load the rollout rake task:\n\n```ruby\nrequire 'rollout'\n\nload 'rollout/tasks/rollout.rake'\n```\n\nAlso, for using the rake tasks, you must set the following env variables\n\n```shell\nROLLOUT_REDIS_HOST=localhost\nROLLOUT_REDIS_PORT=6379\n```\n\n### Usage\n\nTo activate/deactivate features, execute the following rake tasks:\n\n```shell\nbundle exec rake rollout:on[feature_name]\nbundle exec rake rollout:off[feature_name]\n```\n\nTo a gradual activation based on percentages, pass the percentage as the second parameter when executing the `on` task.\n\n```shell\nbundle exec rake rollout:on[feature_name,50]\n```\n\n_NOTE_: In both cases, `feature_name` **must not** include quotes e.g. `bundle exec rake rollout:on['feature_name']`, as the gem will be unable to fetch its activation status if so.\n\nFor listing all the stored feature flags, do:\n\n```shell\nbundle exec rake rollout:list\n```\n\nFor migrating feature flags stored using the old `rollout` gem format (check [migration guide](https://github.com/jcagarcia/rollout-redis/blob/main/MIGRATING_FROM_ROLLOUT_GEM.md)), do:\n\n```shell\nbundle exec rake rollout:migrate_from_rollout_format\n```\n\n## Migrating from rollout gem 🚨\n\nIf you are currently using the unmaintained [rollout](https://github.com/fetlife/rollout) gem, you should consider checking this [migration guide](https://github.com/jcagarcia/rollout-redis/blob/main/MIGRATING_FROM_ROLLOUT_GEM.md) for start using the new `rollout-redis` gem.\n\n### Compatible payloads and keys\n\nYou can use the `.with_old_rollout_gem_compatibility` instance method for making the `rollout-redis` gem work as the the discontinued [rollout](https://github.com/fetlife/rollout) gem in terms of redis storage and format storage. Check the [migration guide](https://github.com/jcagarcia/rollout-redis/blob/main/MIGRATING_FROM_ROLLOUT_GEM.md) for more information.\n\n## Changelog\n\nIf you're interested in seeing the changes and bug fixes between each version of `rollout-redis`, read the [Changelog](https://github.com/jcagarcia/rollout-redis/blob/main/CHANGELOG.md).\n\n## Contributing\n\nWe welcome and appreciate contributions from the open-source community. Before you get started, please take a moment to review the guidelines below.\n\n### How to Contribute\n\n1. Fork the repository.\n2. Clone the repository to your local machine.\n3. Create a new branch for your contribution.\n4. Make your changes and ensure they meet project standards.\n5. Commit your changes with clear messages.\n6. Push your branch to your GitHub repository.\n7. Open a pull request in our repository.\n8. Participate in code review and address feedback.\n9. Once approved, your changes will be merged.\n\n### Development\n\nThis project is dockerized, so be sure you have docker installed in your machine. \n\nOnce you clone the repository, you can use the `Make` commands to build the project.\n\n```shell\nmake build\n```\n\nYou can pass the tests running:\n\n```shell\nmake test\n```\n\n### Issue Tracker\n\nOpen issues on the GitHub issue tracker with clear information.\n\n### Contributors\n\n*   Juan Carlos García - Creator - https://github.com/jcagarcia\n\nThe `rollout-redis` gem is based on the discontinued [rollout](https://github.com/fetlife/rollout) project, created by [James Golick](https://github.com/jamesgolick)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjcagarcia%2Frollout-redis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjcagarcia%2Frollout-redis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjcagarcia%2Frollout-redis/lists"}