---
title: "Flagpole"
url: https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole/
---

# Flagpole

Flagpole is Sentry's internal, options-backed feature flagging library.

Features are defined in the [`sentry-options-automator`](https://github.com/getsentry/sentry-options-automator) repository as yaml objects within the [`options/defaults/flagpole.yml`](https://github.com/getsentry/sentry-options-automator/blob/main/options/default/flagpole.yml) file. These yaml options are pushed to each of our deployments and stored in a database table, where they are later queried and parsed during feature flag evaluation.

Here's the example configuration for a feature named `organizations:is_sentry`, which is enabled for an organization with the slug `sentry`.

```yaml
options:
  "feature.organizations:is_sentry":
    created_at: "2024-06-01T00:00:00.000000"
    enabled: false
    owner:
      - team: hybrid-cloud
      - email: foo@sentry.io
    segments:
      - conditions:
          - operator: in
            value:
              - sentry
            property: organization_slug
        name: is_sentry
        rollout: 100
```

## [Flagpole Feature Yaml Structure](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#flagpole-feature-yaml-structure)

* `created_at`

  The ISO 8601 datetime of when the feature was added to the config yaml.

* `enabled` \[optional]

  The global toggle for the feature flag. Defaults to `True`. Setting this to `False` can be a break-glass safety valve to disable a feature without having to modify existing segments or conditions.

* `segments`

  A wrapper around a list of conditions, acting as a logical grouping of customers/entities to enable the feature flag for. Segments allow you to create `OR` operations with other segments, meaning at least one segment must evaluate to `True` for a feature to be granted. If an empty segments list is provided, the feature will evaluate to `False`.

### [Owner](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#owner)

* `team`

  The name of the team that owns this feature flag

* `email` \[optional]

  The email of the team that owns this feature flag

### [Segments](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#segments)

* `conditions`

  A list of predicates to evaluate for the feature flag to be enabled for this segment. All conditions in a segment must be evaluate to `True` in order for the segment to be enabled. If no conditions are defined, the segment will evaluate to `False`.

* `name`

  A brief description of the segment identifying its intended purpose.

* `rollout` \[optional]

  A percentage of entities to enable the feature for, defined as an integer between `0` - `100`. Defaults to `100`.

### [Conditions](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#conditions)

* `property`

  The property name of the evaluation context entry to match against.

* `value`

  The expected value to compare against the evaluation context's property value, using the provided operator.

* `operator`

  The comparison strategy to apply between the evaluation context's property value and the provided condition value.

### [Operators](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#operators)

Flagpole currently supports the following `operator` types:

* `in`

  Given a list of values, evaluates to `True` if the context property value exists in the list.

* `not_in`

  The inverse of `in`, evaluates to `True` if the context property value does not exist in the provided list.

* `contains`

  Given a single int, string, float, or boolean value, evaluates to `True` if the context property value is a list containing the provided value.

* `not_contains`

  The inverse of `contains`, evaluates to `True` if the context property value is a list which does not contain the provided value.

* `equals`

  Given a single int, string, float, or boolean value, evaluates to `True` if the context property value exactly matches the provided value.

* `not_equals`

  The inverse of `equals`, evaluates to `True` if the context property value does not match the provided value.

## [Evaluation Contexts](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#evaluation-contexts)

When a feature flag is checked, the caller must provide one or more entity objects for the feature handler to match against. These objects are used to construct an `EvaluationContext`, which is essentially a flat dictionary of keys and primitive values. This context is passed to each feature, which provides this context to each segment and condition to enforce whether the feature should be enabled.

### [Context Builders](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#context-builders)

Each evaluation context is built up in stages via a [`ContextBuilder`](https://github.com/getsentry/sentry/blob/3cbf73a389a4ea006cbad9d8c4b8073effe09393/src/flagpole/evaluation_context.py#L54) object.

Each context builder consists of a list of context transformers, which are responsible for creating individual slices of the larger evaluation context.

Here are some common properties we surface via our Sentry and GetSentry context builders that you can use in your conditions:

**System Context Properties**

* `sentry_region` \[str]

  The sentry region or single-tenant the flag check is being performed in.

* `sentry_singletenant` \[bool]

  Whether or not the application is operating in a single-tenant environment.

**Organization Context Properties**

* `organization_id` \[int]

  The organization's ID

* `organization_slug` \[str]

  The organization's slug

* `organization_name` \[str]

  The organization's name

* `organization_is-early-adopter` \[bool]

  Whether or not the organization has the `early_adopter` flag enabled

**Project Context Properties (If checking a project feature)**

* `project_id` \[int]

  The project's ID

* `project_slug` \[str]

  The project's slug

* `project_platform` \[str]

  The project's platform

**User Context Properties (If checking a flag with an actor)**

* `user_id` \[int]

  The active user's ID

* `user_email` \[str]

  The active user's email address. This should only contain Sentry employee email addresses.

* `user_domain` \[str]

  The domain of the active user's email address.

* `user_is-staff` \[bool]

  Is set to `true` for users that have `is_staff`.

* `user_is-superuser` \[bool]

  Is set to `true` for users that have `is_superuser`.

To see the latest context properties available, check out the repo-specific context builders:

* [Sentry Context Builder](https://github.com/getsentry/sentry/blob/master/src/sentry/features/flagpole_context.py)
* [GetSentry Context Builder](https://github.com/getsentry/getsentry/blob/master/getsentry/feature_handlers/getsentry_flagpole_context_builder.py)

## [Rolling out a new Flagpole feature](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#rolling-out-a-new-flagpole-feature)

Creating a new Flagpole Feature is currently a 2 step process:

1. Register a new feature in Sentry's `temporary.py` file or GetSentry's `features.py` file with the Flagpole strategy:

```python
features.add(
    "<feature_scope>:<feature_name>",
    OrganizationFeature,
    FeatureHandlerStrategy.FLAGPOLE
)
```

2. Add a new feature object entry to sentry-options-automator's `flagpole.yml` file. The feature's option name must follow the following format in order to be picked up by Flagpole:

```bash
feature.<feature_scope>:<feature_name>
```

The feature config should not be merged until the registration commit in step 1 has been fully deployed to all target environments. This is because Options Automator will fail to push options to any environments missing the option registration. If this happens, make sure to rerun the options deployment once all environments have been updated to ensure your feature is active.

Once the option change is deployed, the feature checks will immediately be active in all environments and regions.

## [Using Flagpole in single-tenants](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#using-flagpole-in-single-tenants)

To allow your flagpole feature configuration to be used in single-tenant environments, you'll need to add your feature name to the `flagpole.allowed_features` list for each tenant. For example, in `options/regions/acme.yml` add the following:

```yaml
options:
  flagpole.allowed_features: ["organizations:is_sentry"]
```

You can also use the `sentry_singletenant` and `sentry_region` context values in your feature conditions as required.

## [Testing a Flagpole feature locally](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#testing-a-flagpole-feature-locally)

You can test a flagpole feature flag locally using the GetSentry devserver. Because the feature handler for Flagpole only exists in GetSentry, it's not possible to test flagpole features using the Sentry devserver at this time.

Start by creating a new yaml file containing your feature config:

```yaml
options:
  "feature.organizations:is_sentry":
    created_at: "2024-06-01T00:00:00.000000"
    enabled: false
    owner: hybrid-cloud
    segments:
      - conditions:
          - operator: in
            value:
              - sentry
            property: organization_slug
        name: is_sentry
        rollout: 100
```

You can push your feature option to your local devserver using the following `getsentry configoptions` CLI command:

```bash
getsentry configoptions -f <path>/<to>/<your>/<config>.yml -l DEBUG patch
```

If this command runs successfully, your flagpole feature should now be active in your local devserver instance and will persist across runs until you remove the feature option.

To unset your feature, comment out or remove your feature config from the `option` object, and rerun the `getsentry configoptions` command above.

## [Removing Flagpole features](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#removing-flagpole-features)

Because our options automator CI relies on the feature definitions in both Sentry and GetSentry, flags must be removed in a specific order to avoid causing test failures:

1. Remove all flag checks from the codebase and set a default value of `True` for the flag.
2. Once all flag checks have been removed and the changes have been deployed to all environments, remove the feature flag config from options automator.
3. Remove the [feature registration](https://develop.sentry.dev/backend/application-domains/feature-flags/flagpole.md#rolling-out-a-new-flagpole-feature) from GetSentry or Sentry.
