Featurevisor

Use cases

Trunk based development

Merge unfinished work into main every day, behind a flag that stays off wherever users are. Branches stay short, and the work is released when it is ready rather than when it is merged.

Hide the unfinished code

Start from the example with staging and production environments, and keep the new checkout on in staging and off in production:

Command
npx @featurevisor/cli@latest init --example=with-environments
features/checkout.yml
description: Checkout redesign
bucketBy: userId
rules:
staging:
- key: everyone
conditions: '*'
percentage: 100
production:
- key: everyone
conditions: '*'
percentage: 0

Every change to the new checkout merges behind the flag, while the current checkout keeps working:

const context = {
userId: user.id,
}
if (f.isEnabled('checkout', context)) {
// the new checkout, still being built
} else {
// the current checkout
}
Commits land on main every day, and checkout is on in staging and off in production.

Turn it on while you work

To see the new checkout locally without touching the definition, give your development build a sticky value:

const f = createFeaturevisor({
datafile,
stickyFeatures: {
checkout: { enabled: true },
},
})

Sticky values win over the datafile, and stay out of what you commit to the Featurevisor project.

Test both paths

Until the flag is gone, both code paths ship. Test each in your application's tests, with checkout sticky on and off. In the Featurevisor project, a test spec pins what each environment gets, so nobody turns it on in production by accident:

tests/features/checkout.spec.yml
feature: checkout
assertions:
- description: On in staging
environment: staging
at: 90
expectedToBeEnabled: true
- description: Off in production
environment: production
at: 10
expectedToBeEnabled: false

What a flag cannot hide

A flag only decides which code path runs. It cannot hide:

  • database migrations, which run whatever the flag says
  • side effects outside the code it guards, such as jobs and emails
  • changes to an API that other services call

Make those changes so the current code keeps working with them, before the flag turns on anywhere.

Release and remove

When the new checkout is complete, release it as Decoupled releases describes. Once it is at 100% everywhere, delete the old code path, then deprecate and archive the flag, so it does not linger. With code generation, regenerating after archiving turns any use you missed into a compile error.

Previous
Progressive delivery