Advanced
Environments
Featurevisor is highly configurable and allows us to have any number of custom environments (like development, staging, and production). By default, projects have no environments at all.
There are 2 ways to configure environments in Featurevisor:
- environment specific data in individual self-contained feature definitions
- no environments at all
Custom environments#
If your project needs environments, it is recommended that we have at least staging and production environments in our project.
Adding environments#
We can add more environments as needed:
module.exports = { tags: [ 'web', 'mobile' ], environments: [ 'staging', 'production', // add more environments here... ],}Above configuration will help us define our features and their rules against each environment as follows:
Environment specific rules#
description: My featuretags: - webbucketBy: userId# rules per each environmentrules: staging: - key: everyone segments: '*' percentage: 100 production: - key: everyone segments: '*' percentage: 0See also force and expose for more information.
Generated datafiles#
And the datafiles will be built per each environment in datafiles directory:
$ tree datafiles.├── staging/│ ├── featurevisor-web.json│ └── featurevisor-mobile.json├── production/│ ├── featurevisor-web.json│ └── featurevisor-mobile.jsonEnvironment lanes with sets#
With the environments config above, environment specific rules, force, and expose maps live inside the same feature file.
There is another way to model environments that some teams prefer: treat dev, staging, and production as independent release lanes using sets, and move changes from one lane to the next using promotions.
This approach is useful when you want each lane to be fully separate, so the same feature can have a very different definition in dev than in production, and changes flow forward only when you promote them.
You can scaffold a ready-made project for this with:
$ npx featurevisor init --example=environmentsConfiguration#
With this approach you do not define environments. You enable sets instead, and add promotionFlows to keep promotions moving in one direction:
module.exports = { sets: true, tags: ['all'], // only allow promotions to move forward, one lane at a time promotionFlows: [ { from: 'dev', to: 'staging' }, { from: 'staging', to: 'production' }, ],}One set per lane#
Each lane is a set with its own definitions under sets/<lane>/:
sets/├── dev/│ ├── attributes/│ ├── segments/│ ├── features/│ ├── targets/│ └── tests/├── staging/│ └── ...└── production/ └── ...The same feature key can live in every lane with different rules. Because there are no environments, rules are authored directly without an environment key:
description: New checkout flow in devtags: - allbucketBy: userId# fully rolled out in devrules: - key: everyone segments: '*' percentage: 100description: New checkout flow in productiontags: - allbucketBy: userId# still off in productionrules: - key: everyone segments: '*' percentage: 0Building datafiles#
Building writes datafiles under a directory per lane:
datafiles/dev/featurevisor-all.jsondatafiles/staging/featurevisor-all.jsondatafiles/production/featurevisor-all.jsonPromoting between lanes#
When a feature is ready to move to the next lane, promote it:
$ npx featurevisor promote --from=dev --to=staging --applyThe promotionFlows configuration above makes sure promotions only move forward, so promoting straight from dev to production is rejected.
Read more in Sets and Promotions.
No environments#
Projects have no environments by default. You can omit environments from your configuration:
module.exports = { tags: [ 'web', 'mobile' ],}This will allow us to define our rollout rules directly without needing any environment specific keys:
description: My featuretags: - webbucketBy: userId# rules without needing environment specific keysrules: - key: everyone segments: '*' percentage: 100The datafiles will be built without any environment:
$ tree datafiles.├── featurevisor-web.json├── featurevisor-mobile.json
