<commit_before># Feature Switches

### Status: Alpha (Don't use in production)

## Summary

A small gem for putting feature switches into your application that allow you
to dynamically enable features to a percentage of users or specific cohort
groups without a code deploy. There are some excellent gems that provide this
functionality already -- [rollout](https://github.com/jamesgolick/rollout) and
[flipper](https://github.com/jnunemaker/flipper).  This project is an
experiment aiming for a specific set of design goals:

1. Reduce the chatter in the protocol between a node checking to see if a
   feature is enabled and the backend storage system. We're going to be reading
   this data far more often than we're writing it so we want to aggressively
   cache, but...

2. Ensure all nodes get the latest configuration data as soon as possible. A
   cache that expires given a certain TTL can't work as a client isn't
   guaranteed to talking to the same instance of our application on each
   request. A feature disappearing and reappearing depending on which
   application server instance a user hits is a bug.

3. Allow for extension with new backends that support change notification;
   specifically distributed system synchronization backends like Zookeeper and
   perhaps doozerd. Right now it's initially implemented against Redis and
   Postgres.

4. Ensure that any kind of identifier can be used; not just an object that
   responds to `id` We want to peg our switches on things that aren't
   ActiveRecord objects (e.g., incoming phone numbers, etc).

5. Expose a memorable CLI as `irb` is primarily how we configure the feature
   switches.

## Supported Backends

* Redis
* Postgres
* In-memory (for testing)

## Design

Switches uses a backend for both storage of feature configuration data and for
notifying sibling nodes that a change has been made. We'll look at how this
works against the Redis backend.

On startup, switches will connect to Redis twice: once for querying and setting
configuration data and one for subscribing to a pub/sub channel of change
notifications. When a change is made to configuration data, an extra call is
made to Redis to publish a change notification. Once this change notification is
received by other listening nodes they will refetch the configuration data
and update their local stores.

     Node A              Redis               Node B
       |                   |                   |
       |                   |<-subscribe--------|
       |                   |                   |
       |--------------set->|                   |
       |                   |                   |
       |-----notify(item)->|-notified(update)->|
       |                   |                   |
       |                   |<-get--------------|
       |                   |                   |
       |                   |                   |

This allows a node to validate if a user can pass through a feature switch using
in-memory data without a querying a backend but ensures that each node is using
the same data to make the decision.

## Installation

In your Gemfile:

```ruby
  gem "feature_switches"
```

### Postgres Backend

Switches connects to whatever database is specified as the DATABASE_URL in
your environment. Note that switches will connect to Postgres twice for each
node. This is important as Postgres will fork a new process for each connection
so ensure you have the overhead before using this backend.

To use Postgres a table called `switches` must be created in your database.
Two rake tasks have been included to create and drop this table:

1. Add this to your Rakefile:<commit_msg>Remove lie from README<commit_after># Feature Switches

### Status: Alpha (Don't use in production)

## Summary

A small gem for putting feature switches into your application that allow you
to dynamically enable features to a percentage of users or specific cohort
groups without a code deploy. There are some excellent gems that provide this
functionality already -- [rollout](https://github.com/jamesgolick/rollout) and
[flipper](https://github.com/jnunemaker/flipper).  This project is an
experiment aiming for a specific set of design goals:

1. Reduce the chatter in the protocol between a node checking to see if a
   feature is enabled and the backend storage system. We're going to be reading
   this data far more often than we're writing it so we want to aggressively
   cache, but...

2. Ensure all nodes get the latest configuration data as soon as possible. A
   cache that expires given a certain TTL can't work as a client isn't
   guaranteed to talking to the same instance of our application on each
   request. A feature disappearing and reappearing depending on which
   application server instance a user hits is a bug.

3. Allow for extension with new backends that support change notification;
   specifically distributed system synchronization backends like Zookeeper and
   perhaps doozerd. Right now it's initially implemented against Redis and
   Postgres.

4. Ensure that any kind of identifier can be used; not just an object that
   responds to `id` We want to peg our switches on things that aren't
   ActiveRecord objects (e.g., incoming phone numbers, etc).

5. Expose a memorable CLI as `irb` is primarily how we configure the feature
   switches.

## Supported Backends

* Redis
* Postgres
* In-memory (for testing)

## Design

Switches uses a backend for both storage of feature configuration data and for
notifying sibling nodes that a change has been made. We'll look at how this
works against the Redis backend.

On startup, switches will connect to Redis twice: once for querying and setting
configuration data and one for subscribing to a pub/sub channel of change
notifications. When a change is made to configuration data, an extra call is
made to Redis to publish a change notification. Once this change notification is
received by other listening nodes they will refetch the configuration data
and update their local stores.

     Node A              Redis               Node B
       |                   |                   |
       |                   |<-subscribe--------|
       |                   |                   |
       |--------------set->|                   |
       |                   |                   |
       |-----notify(item)->|-notified(update)->|
       |                   |                   |
       |                   |<-get--------------|
       |                   |                   |
       |                   |                   |

This allows a node to validate if a user can pass through a feature switch using
in-memory data without a querying a backend but ensures that each node is using
the same data to make the decision.

## Installation

In your Gemfile:

```ruby
  gem "feature_switches"
```

### Postgres Backend

Note that switches will connect to Postgres twice for each node. This is important
as Postgres will fork a new process for each connection so ensure you have the
overhead before using this backend.

To use Postgres a table called `switches` must be created in your database.
Two rake tasks have been included to create and drop this table:

1. Add this to your Rakefile:
{'fraction_non_alphanumeric': 0.05623100303951368, 'fraction_numerical': 0.0016579165515335729, 'mean_word_length': 2.4736084452975047, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4166365', 'n_tokens_mistral': 1770, 'n_tokens_neox': 1669, 'n_words': 963}