You can define arbitrarily complex types for your inputs. For example, the User input type can have a field with a list of roles:
Complex flag types
In addition to simple Boolean feature flags, you can have flags with String, Int, and Float types, and custom enum, object, and list types. For example, you can define the following flags on the Root type:
Flag-specific targeting attributes
Instead of adding new input types and targeting attributes to the top-level Context, you can add them directly to specific flags.
If a targeting attribute is only relevant to a specific flag, this avoids polluting the top-level scope with it, and ensures it can't be accidentally used in the targeting logic of other flags.
It also lets you pass different attribute values to a flag in the same browser session. So you can have flags that depend on the session state like user input, selected options, the current view, etc.
For example, you can define a priceId flag that depends on the provided usageAmount:
Flag lifecycle
You can manage flag lifecycle by marking flags as deprecated in your schema from the UI or in GraphQL with the @deprecated directive.
Schema migrations
To make large changes to your schema, e.g. sweeping refactors, you can use branches and pull requests to easily migrate your schema.