Hone logo
Hone
Problems

Implementing a Feature Flagging System in Go

Building robust software often involves the ability to control the rollout of new features. This is crucial for A/B testing, canary releases, and gradual rollouts, allowing developers to test new functionality with a subset of users before a full release. Your challenge is to implement a foundational feature flagging system in Go.

Problem Description

You need to design and implement a Go package that allows for the dynamic enabling or disabling of features based on specific criteria. This system should be able to evaluate whether a feature is "on" or "off" for a given user or request.

Key Requirements:

  1. Feature Definition: Define a way to represent a feature with a unique identifier (e.g., a string name) and its current state (enabled/disabled).
  2. Evaluation Logic: Implement a function that takes a feature identifier and a context (representing the user or request) and returns true if the feature is enabled for that context, and false otherwise.
  3. Contextual Targeting: The system should support basic contextual targeting. For this challenge, we will focus on a simple form of targeting: enabling a feature for a certain percentage of users.
  4. Configuration: The feature states and targeting rules should be configurable, allowing them to be changed without modifying the core code. For this challenge, assume the configuration is provided upfront as a data structure.
  5. No External Dependencies: The solution should not rely on external databases or third-party services for its core functionality.

Expected Behavior:

  • When a feature is "enabled" globally, it should be considered enabled for all contexts unless specific disabling rules apply (not required for this version).
  • When a feature is "disabled" globally, it should be considered disabled for all contexts.
  • When a feature is enabled with a percentage rollout, the IsEnabled function should return true for approximately that percentage of unique contexts. The uniqueness of a context will be determined by a specific identifier within the context.

Edge Cases:

  • A feature that is not defined in the configuration should be treated as disabled.
  • A context with no unique identifier should be handled gracefully (e.g., treated as disabled for percentage rollouts, or a default behavior).

Examples

Example 1: Basic Feature Enablement

Input Configuration:

{
  "features": {
    "new_dashboard": {
      "enabled": true
    },
    "experimental_search": {
      "enabled": false
    }
  }
}

Input Context (User ID): "user123" Feature Name: "new_dashboard"

Output: true

Explanation: The new_dashboard feature is globally enabled in the configuration.

Input Context (User ID): "user123" Feature Name: "experimental_search"

Output: false

Explanation: The experimental_search feature is globally disabled in the configuration.

Example 2: Percentage Rollout

Input Configuration:

{
  "features": {
    "new_recommendations": {
      "enabled": true,
      "rollout_percentage": 50
    }
  }
}

Input Contexts:

  • User ID: "user456"
  • User ID: "user789"
  • User ID: "userabc"
  • User ID: "userdef"
  • User ID: "userghi"

Feature Name: "new_recommendations"

Expected Output (illustrative, actual output will vary due to hashing):

  • "user456": true
  • "user789": false
  • "userabc": true
  • "userdef": false
  • "userghi": true

Explanation: The new_recommendations feature is enabled with a 50% rollout. The system uses a stable hashing mechanism (e.g., based on the User ID) to determine which users fall into the 50% group. In this illustrative output, 3 out of 5 users are in the enabled group.

Example 3: Undefined Feature

Input Configuration:

{
  "features": {
    "new_dashboard": {
      "enabled": true
    }
  }
}

Input Context (User ID): "userxyz" Feature Name: "non_existent_feature"

Output: false

Explanation: The non_existent_feature is not defined in the configuration, so it defaults to being disabled.

Constraints

  • The feature names and user identifiers will be strings.
  • rollout_percentage will be an integer between 0 and 100 (inclusive).
  • The hashing algorithm used for percentage rollouts must be deterministic to ensure consistent results for the same input.

Notes

  • Consider how you will represent the configuration data. A struct in Go is a natural fit.
  • For percentage rollouts, you'll need a way to deterministically map a user identifier to a number within a specific range. Think about hashing functions.
  • The context for evaluation could be a simple struct containing relevant user information, such as a User ID.
  • The focus of this challenge is on the core logic of feature evaluation and percentage-based rollout. More complex targeting rules (e.g., by user attributes, geography) are out of scope for this exercise.
Loading editor...
go