Migration guides
Migrating from v2 to v3
- Migrate in two steps
- Project configuration
- Environments are off by defaultBreaking
- Split environment files removedBreaking
- Scopes replaced by targetsBreaking
- Namespace separatorBreaking
- SetsNew
- PromotionsNew
- Defining features
- Testing features
- CLI usage
- JavaScript SDK usage
- Upgrade to latest SDKNew
- Creating an instanceBreaking
- Instance type renamedBreaking
- Options type renamedBreaking
- Evaluating global variablesNew
- setDatafile merges by defaultSoft breaking
- Sticky values belong to instancesBreaking
- Child instances use a context snapshotBreaking
- Explicit defaults preserve falsey valuesFix
- Diagnostics instead of loggerBreaking
- Modules instead of hooksBreaking
- Public SDK surface reducedBreaking
- Other SDK usage
- React and Vue SDK usage
- Migration checklist
Detailed guide for migrating existing Featurevisor projects and applications from v2 to the latest v3.x release.
Migrate in two steps#
You do not have to migrate everything at once. The safest path is linear, with applications first and the project afterwards:
- Upgrade your applications: update each application's SDK while it continues to consume the existing v2 datafiles.
- Upgrade your Featurevisor project: update the CLI, adjust your configuration and definitions, build the datafiles, and deploy them.
Schema version 2 continues#
Generated datafiles continue to use schema version 2. Current SDKs can read existing v2 datafiles, which makes it safe to upgrade applications before publishing new datafiles.
V3 datafiles can contain optional fields for newer functionality, including global variables and requiredFeatures. Older SDKs may ignore those fields and evaluate a feature or variable without the intended prerequisite. Upgrade every application that consumes a datafile before enabling those definitions in it.
Behaviour changes#
Also review segments.not, because it now uses the same implicit AND semantics as conditions.
If a project does not use the newer fields or multi-child segments.not, the migration order is more flexible. Upgrading applications first remains the simpler default because published datafiles can then adopt current functionality without mixed SDK behaviour.
Project configuration#
Environments are off by default Breaking#
In v2, every project had staging and production environments by default. In v3, projects have no environments unless you declare them.
If your project uses environments, declare them explicitly in your configuration:
module.exports = { // staging and production // were assumed by default tags: ['all'],}module.exports = { environments: [ 'staging', 'production', ], tags: ['all'],}If your project does not need environments, you can leave environments out, and author your rules, force, and expose directly without an environment key.
The old environments: false value is no longer needed. Remove the property instead.
Learn more in Environments page.
Split environment files removed Breaking#
The splitByEnvironment option and the top-level environments/ definition directory have been removed. Environment-specific rules, force, and expose now belong in their feature file, keyed by environment.
features/ checkout.ymlenvironments/ staging/ checkout.yml production/ checkout.ymldescription: CheckoutbucketBy: userIdrules: staging: - key: everyone segments: '*' percentage: 100 production: - key: everyone segments: '*' percentage: 0Remove splitByEnvironment from featurevisor.config.js after moving the files. If those directories represented independently promoted copies rather than environment-specific rollout fields, consider migrating them to Sets instead.
Scopes replaced by targets Breaking#
The scopes configuration key has been removed. Datafiles are now built from targets, which live as files in the targets directory.
module.exports = { scopes: [ { name: 'browsers', tag: 'web', context: { platform: 'web' }, }, ],}description: Web browserstag: webcontext: platform: webA target's tag, tags, and context work exactly like a scope did, including the or and and selectors. If scopes is still present in your configuration, Featurevisor ignores it. Migrate each old scope to a target file, because obsolete scopes entries no longer build any datafiles.
Learn more in Targets and Scopes pages.
Namespace separator Breaking#
Namespaced feature and segment keys now use a dot (.) as their separator by default, instead of a slash (/).
This means features/checkout/feature1.yml is now referred to as checkout.feature1 instead of checkout/feature1, both in your application and in your test specs.
To keep the old slash-separated keys, set namespaceCharacter in your configuration:
module.exports = { namespaceCharacter: '/',}Learn more in Namespaces page.
Sets New#
You can now split a project into independent trees called sets, each owning its own attributes, segments, features, targets, and tests.
module.exports = { sets: true, tags: ['all'],}This is useful for modeling release lanes like dev, staging, and production, or distinct surfaces like storefront and admin, from a single repository.
Learn more in Sets page.
Promotions New#
In a project with sets, you can copy definitions from one set to another using promotions. You can optionally constrain which promotions are allowed with promotionFlows:
module.exports = { sets: true, tags: ['all'], promotionFlows: [ { from: 'dev', to: 'staging' }, { from: 'staging', to: 'production' }, ],}Learn more in Promotions page.
Defining features#
Tags are now optional New#
In v2, every feature needed at least one tag:
description: My featuretags: - allbucketBy: userIdrules: - key: everyone segments: '*' percentage: 100description: My feature# Tags can now be omitted optionally.# Target definitions can still pick them up.bucketBy: userIdrules: - key: everyone segments: '*' percentage: 100In v3, the tags property is optional and can be removed when the feature does not need to belong to a tagged group.
A feature without tags is still included in targets that do not narrow down by tag.
Learn more in Features section.
Required features New#
Feature dependencies now use requiredFeatures. The object form also renames key to feature:
required: - key: checkout # no way to check for disabled features variation: treatmentrequiredFeatures: - feature: checkout enabled: true # or false variation: treatmentWhen only one enabled feature is required, the declaration can stay on one line:
requiredFeatures: checkoutenabled is optional, defaults to true, and compares against the SDK's ordinary isEnabled() result. Set it to false when the dependency must be disabled. The variation compares against getVariation(), and both checks can be used together:
requiredFeatures: - feature: legacyCheckout enabled: false variation: controlGlobal variables and their overrides use the same requiredFeatures forms. Learn more in Features and Global variables.
Global variables New#
Featurevisor always had variables inside features, but now they can also be defined independent of features.
Global variables are typed configuration values with their own lifecycle. They are defined under variables/ rather than inside a feature:
description: Support email addresstags: - webtype: string# overrides by environment# if Featurevisor project is setup with environmentsoverrides: production: - key: netherlands conditions: # or using segments attribute: country operator: equals value: nlIn the SDK, the existing two-key call continues to evaluate a variable owned by a feature. A one-key call evaluates a global variable:
// feature variableconst currency = f.getVariable( 'checkout', 'currency');// no global variable support// feature variable (still supported)const currency = f.getVariable( 'checkout', 'currency');// global variableconst supportEmail = f.getVariable( // no need for feature key as first argument 'supportEmail')They support tags, required features, ordered overrides, nested refinements, sticky values, target selection, test specs, promotions, Catalog relationships, and generated TypeScript types. Nested override values are resolved while building the datafile, so SDKs still use first match evaluation at runtime.
Targets can use includeVariables and excludeVariables. A target without tag or key selectors includes every active feature and global variable. Required feature chains and referenced segments are included automatically.
Learn more in Global variables and Targets.
Feature and global variable key collisions New#
Feature and global variable keys are expected to be different by default. Featurevisor itself do not have any limitation to allow this, but it is not recommended to do so as it risks confusion for human readers.
Featurevisor reports a lint error when both use the same key. Rename one of the definitions where possible so generated APIs, providers, and SDK calls remain unambiguous.
If the overlap is intentional, allow it explicitly:
module.exports = { allowFeatureAndGlobalVariableKeyCollisions: true,}JavaScript can distinguish feature and global variable calls through overloads. Other languages and integrations may use dedicated global variable methods or prefixes, so distinct keys remain the most portable choice.
Reserved keys New#
Feature keys, global variable keys, and feature variable keys reserve feature, variation, and variable by default. This prevents ambiguous selectors in integrations such as OpenFeature.
Use reservedKeys to replace the defaults when a project needs different names:
module.exports = { reservedKeys: ['feature', 'variation', 'variable'],}An empty array disables this check. The comparison is exact and case sensitive.
Variable overrides New#
Feature and global variable overrides can use a stable key, requiredFeatures, and either conditions or segments. Define exactly one complete value or an explicit partial mutate operation.
Global variable overrides may nest for hierarchical targeting. Feature variable overrides remain flat. Detailed evaluations expose the matched override key and index, while nested global overrides also expose their authored key path.
Global variable overrides always require keys. Feature variable override keys remain optional so existing v2 projects continue to lint, but keys are recommended for stable evaluation details and promotion.
Projects can opt into the stricter behaviour before the next major release:
module.exports = { requireOverrideKeysInFeatures: true,}The option defaults to false. When enabled, linting fails if any variable override inside a feature rule or variation does not have a key.
Learn more in Feature variables and Global variables.
not uses implicit AND semantics Breaking#
For both conditions and rule segments, direct children of not are treated as an implicit AND. In v3, segments.not is aligned with the condition behaviour.
Use a nested or when the intention is "none of these match":
rules: - key: neither-premium-nor-internal segments: not: - or: - premium - internal percentage: 100Use a nested and when the intention is "not all of these match":
rules: - key: not-both-premium-and-internal segments: not: - and: - premium - internal percentage: 100Keep v2 and v3 SDKs compatible
During a gradual SDK rollout, avoid placing multiple segment names directly under not. Put one explicit or or and group under it instead.
Both SDK versions then see a single direct child and negate the same grouped result:
not: [{ or: [...] }]means none of the listed segments match.not: [{ and: [...] }]means not all of the listed segments match.
For an existing v2 rule with several direct children under not, wrap those children in or before publishing a datafile that will be consumed by both v2 and v3 applications. This preserves the v2 "none match" behaviour throughout the transition. After every application uses a v3 SDK, the explicit grouping can remain because it is clearer and behaves identically.
Empty and, or, and not arrays are now rejected during linting. Update any generated or placeholder expressions before upgrading.
Portable regex and date conditions Breaking#
Regular expression conditions now accept only the portable g, i, m, and s flags. Remove JavaScript specific flags such as u and y from project definitions before building v3 datafiles.
Values used with before and after must be complete ISO 8601 timestamps with an explicit timezone, such as 2026-07-23T10:00:00Z or 2026-07-23T12:00:00+02:00. Date-only values and timestamps without a timezone are rejected. This keeps evaluation consistent across browser, server, and non-JavaScript SDKs.
Promotable definitions New#
In a project with sets, you can protect an existing destination definition from later promotion updates by setting promotable: false. A missing destination definition is still created. On rules, a source rule with this field is omitted and an existing destination rule is preserved. This is supported on features, rules, segments, attributes, groups, schemas, targets, and test specs.
description: My featurepromotable: false# ...Learn more in Promotions page.
Testing features#
Targeting datafiles in assertions Breaking#
The scope and tag properties in test assertions have been replaced by a single target property.
feature: myFeatureassertions: - environment: production scope: browsers at: 50 context: {} expectedToBeEnabled: truefeature: myFeatureassertions: - environment: production target: browsers at: 50 context: {} expectedToBeEnabled: trueThe --with-scopes and --with-tags CLI flags are no longer needed. The test runner builds target datafiles in memory automatically. Old scripts may still pass these flags, but they are ignored.
Learn more in Testing page.
Testing sets New#
In a project with sets, tests run for every set by default. You can run tests for a single set with --set:
$ npx featurevisor test --set=storefrontCLI usage#
Upgrade to latest CLI New#
In your Featurevisor project repository:
$ npm install --save @featurevisor/cli@3Building datafiles from targets Breaking#
Datafiles are no longer built per tag automatically. You now need at least one target for the build to produce anything.
The smallest possible target includes all of your non-archived features:
description: All featuresThen build as usual:
$ npx featurevisor buildDatafile naming Breaking#
Because datafiles are built from targets now, the tag- prefix in datafile names is gone. A datafile is named after the target that produced it.
$ tree datafiles.├── production│ └── featurevisor-tag-web.json└── staging └── featurevisor-tag-web.json$ tree datafiles.├── production│ └── featurevisor-web.json└── staging └── featurevisor-web.jsonDefine a target named web (with tag: web) to produce featurevisor-web.json.
To maintain backwards compatibility, you can create new targets named tag-web and tag-mobile to produce featurevisor-tag-web.json and featurevisor-tag-mobile.json respectively.
Learn more in Building datafiles page.
Schema version selection removed Breaking#
Featurevisor v3 no longer builds v1-compatible datafiles. Generated datafiles always use schema version 2, and still include the normal schemaVersion: "2" field.
The old --schema-version and --schemaVersion flags are no longer part of active CLI usage. If they are still passed by old scripts, they are ignored and datafiles are still generated as schema version 2.
If you still have an application consuming v1 datafiles, keep building those datafiles with an older Featurevisor v2 CLI until the application can move to a v2-datafile-compatible SDK.
Catalog instead of site Breaking#
The old site package and command have been replaced by the new standalone @featurevisor/catalog package, exposed through the catalog command.
$ npx featurevisor site export$ npx featurevisor site serve$ npx featurevisor catalog export$ npx featurevisor catalog serveThe default export directory changes from out/ to catalog/. Replace siteExportDirectoryPath with catalogDirectoryPath if your project customizes it, and update deployment workflows to publish the new directory. Running npx featurevisor catalog without a subcommand now starts a watched local development session.
Learn more in Catalog page.
Promote command New#
In a project with sets, you can preview and apply promotions between sets:
$ npx featurevisor promote --from=dev --to=staging$ npx featurevisor promote --from=dev --to=staging --apply$ npx featurevisor promote --from=dev --to=staging --target=checkout --applyPromotion filters such as --target, --tag, --includeFeatures, and --excludeFeatures limit the selected features while automatically including the segments they reference.
Learn more in Promotions page.
Per-feature generated modules removed Breaking#
The TypeScript code generator no longer creates individual *Feature.ts namespaces. The --no-individual-features option has also been removed because the function API is now the only generated API.
Run the v3 code generator with the same project-level command, without --no-individual-features:
$ npx featurevisor generate-code \ --language typescript \ --out-dir ./src \ --reactDelete the old generated output before running the v3 generator so stale *Feature.ts files do not remain in your project. Replace namespace imports with the typed shared functions:
import { CheckoutFeature } from '@yourorg/features'const enabled = CheckoutFeature.isEnabled(context)const variation = CheckoutFeature.getVariation(context)const color = CheckoutFeature.getColor(context)import { isEnabled, getVariation, getVariable,} from '@yourorg/features'const enabled = isEnabled('checkout', context)const variation = getVariation('checkout', context)const color = getVariable('checkout', 'color', context)Feature keys, variable keys, variation values, variable values, and context remain type safe through the shared generated functions. Learn more in Code Generation.
Generated projects now use FeatureVariableKey and FeatureVariableType for variables owned by a feature, and GlobalVariableKey and GlobalVariableType for independent variables. The earlier VariableKey and VariableType names remain as deprecated aliases for feature variables during the migration window.
Code generation also accepts repeatable --tag and --target options in v3. All supplied selectors form a union, allowing one generated package to cover several target datafiles.
In a project with sets enabled, generate-code requires --set=<set> because one generated package represents one set's definitions.
Target selection is also available on build, test, evaluate, benchmark, assess-distribution, list --features, and info. The option is repeatable where several targets can be processed. Each runtime command evaluates every selected target independently. A normal build writes every selected target datafile, while build --json and build --print accept only one target because they emit one datafile.
Working with a single set New#
Most commands accept a --set flag to scope them to one set:
$ npx featurevisor build --set=storefront$ npx featurevisor test --set=storefrontJavaScript SDK usage#
Upgrade to latest SDK New#
In your application repository:
$ npm install --save @featurevisor/sdk@3Creating an instance Breaking#
createInstance has been renamed to createFeaturevisor.
import { createInstance } from '@featurevisor/sdk'const f = createInstance({ datafile: datafileContent,})import { createFeaturevisor } from '@featurevisor/sdk'const f = createFeaturevisor({ datafile: datafileContent,})Instance type renamed Breaking#
The FeaturevisorInstance type has been renamed to Featurevisor.
import type { FeaturevisorInstance } from '@featurevisor/sdk'let f: FeaturevisorInstanceimport type { Featurevisor } from '@featurevisor/sdk'let f: FeaturevisorOptions type renamed Breaking#
The constructor options type has been renamed from InstanceOptions to FeaturevisorOptions.
import type { InstanceOptions } from '@featurevisor/sdk'const options: InstanceOptions = { datafile: datafileContent,}import type { FeaturevisorOptions } from '@featurevisor/sdk'const options: FeaturevisorOptions = { datafile: datafileContent,}Learn more in JavaScript SDK page.
Evaluating global variables New#
The JavaScript SDK uses overloaded variable methods. Pass a feature key and variable key for a feature variable, or pass a global variable key and optional context for an independent value:
// feature variableconst colour = f.getVariable('checkout', 'colour', context)// global variableconst supportEmail = f.getVariable('supportEmail', context)Type specific methods such as getVariableString() use the same signatures. Use evaluateVariable() for detailed results, getVariableKeys() without a feature key to list global keys, and getVariableEvaluations() to evaluate a global variable snapshot.
Sticky state is separated into stickyFeatures and stickyVariables, with matching setter methods. Modules can observe both feature and global variable evaluations through beforeEvaluation and afterEvaluation.
React and Vue hooks follow the same overloaded useVariable() API. Generated TypeScript wrappers preserve the feature and global variable value types.
Learn more in JavaScript SDK, React, and Vue.js.
setDatafile merges by default Soft breaking#
In v2, calling setDatafile replaced the instance's datafile. In v3, it merges with the existing datafile by default.
Incoming features and segments override matching keys, while existing ones that are missing from the incoming datafile are kept. To get the old replacing behaviour, pass true as the second argument.
// always replacedf.setDatafile(datafileContent)// merges by defaultf.setDatafile(datafileContent)// pass true to replace entirelyf.setDatafile(datafileContent, true)Merging makes it possible to load smaller datafiles on demand. Learn more in Loading datafiles on demand.
Sticky values belong to instances Breaking#
The per-evaluation sticky override has been removed. Set sticky values on the main instance, or give a child instance its own sticky values when spawning it.
const enabled = f.isEnabled('checkout', context, { sticky: stickyFeatures,})f.setStickyFeatures(stickyFeatures)const enabled = f.isEnabled('checkout', context)For isolated state, use f.spawn(context, { stickyFeatures }) and evaluate through the returned child instance.
Child instances use a context snapshot Breaking#
A child snapshots the parent context keys that exist when spawn is called. Later changes to those parent keys do not alter the child. New keys added to the parent after spawning are still inherited. Context supplied to an individual child evaluation is merged for that call only.
Child instances also own the event subscriptions they create. Call child.close() when the child is no longer needed so delegated parent subscriptions are removed.
Explicit defaults preserve falsey values Fix#
Variation and variable defaults are selected by whether the option is present, not by whether its value is truthy. Values such as false, 0, an empty string, and null remain intentional defaults. Review wrappers around the SDK and avoid replacing these values with fallback expressions.
Diagnostics instead of logger Breaking#
The logger option and the createLogger function have been removed. The SDK now reports diagnostics, which you control with logLevel and an optional onDiagnostic handler.
import { createInstance, createLogger,} from '@featurevisor/sdk'const f = createInstance({ logger: createLogger({ level: 'debug', }),})import { createFeaturevisor } from '@featurevisor/sdk'const f = createFeaturevisor({ logLevel: 'debug',})You can pass your own handler if you do not want diagnostics printed to the console:
const f = createFeaturevisor({ logLevel: 'info', onDiagnostic: function (diagnostic) { // send to your observability system },})The setLogLevel method still works for changing the level at runtime.
Learn more in Diagnostics section.
Modules instead of hooks Breaking#
The hooks API has been replaced by the modules API. The Hook type is now FeaturevisorModule, hooks is now modules, and addHook is now addModule.
Your existing before, after, bucketKey, and bucketValue callbacks carry over unchanged. The feature-only before and after callbacks are deprecated. Use beforeEvaluation and afterEvaluation for new modules so the same callbacks can handle both feature and global variable evaluations. Modules also add an optional setup lifecycle and a close callback.
import { createInstance } from '@featurevisor/sdk'const f = createInstance({ hooks: [myCustomHook],})const removeHook = f.addHook(myCustomHook)import { createFeaturevisor } from '@featurevisor/sdk'const f = createFeaturevisor({ modules: [myCustomModule],})const removeModule = f.addModule(myCustomModule)await removeModule?.()await f.removeModule('my-custom-module')The old interceptContext, configureBucketKey, and configureBucketValue options, which were already replaced by hooks in v2, are now expressed as modules. Module cleanup can be asynchronous, so the function returned by addModule and removeModule should be awaited.
Learn more in Modules section.
Public SDK surface reduced Breaking#
The package root now focuses on createFeaturevisor, the Featurevisor type, child instances, evaluations, events, diagnostics, modules, and Featurevisor data types.
DatafileReader, logger and emitter implementations, evaluator dependency objects, and other internal helpers are no longer public APIs. If application code used DatafileReader to inspect the active datafile, use the corresponding instance methods instead:
| Removed usage | Instance replacement |
|---|---|
reader.getRevision() | f.getRevision() |
reader.getSchemaVersion() | f.getSchemaVersion() |
reader.getSegment(key) | f.getSegment(key) |
reader.getFeature(key) | f.getFeature(key) |
reader.getFeatureKeys() | f.getFeatureKeys() |
reader.getVariableKeys(featureKey) | f.getVariableKeys(featureKey) |
reader.hasVariations(featureKey) | f.hasVariations(featureKey) |
Remove direct imports of undocumented logger, emitter, reader, and evaluator helpers. Use diagnostics, events, and the main instance API instead.
The v1-only DatafileContentV1, FeatureV1, VariationV1, and VariableV1 types have also been removed. Use the normal v2 datafile types. VariableValue no longer includes undefined; missing evaluated values use null.
Other SDK usage#
The v3 SDKs use the same Featurevisor focused factory naming as the JavaScript SDK. The old instance factory names are removed as a clean breaking change.
| SDK | v2 factory | v3 factory |
|---|---|---|
| Go | NewFeaturevisor | CreateFeaturevisor |
| Swift | createInstance | createFeaturevisor |
| Java | Featurevisor.createInstance | Featurevisor.createFeaturevisor |
| Ruby | Featurevisor.create_instance | Featurevisor.create_featurevisor |
| Python | create_instance | create_featurevisor |
| PHP | Featurevisor::createInstance | Featurevisor::createFeaturevisor |
The PHP SDK now requires PHP 8.0 or newer. Applications that must remain on PHP 7.4 should continue using the previous Featurevisor PHP SDK release until their runtime is upgraded.
Go now uses FeaturevisorOptions instead of Options. Java now uses Featurevisor.FeaturevisorOptions instead of Featurevisor.Options. Swift and Python expose the main instance as Featurevisor instead of FeaturevisorInstance.
Update imports, type annotations, factory calls, and options type names together when upgrading an application. See the relevant SDK guide for language specific examples.
Custom logger injection has also been removed from all v3 SDKs. Configure diagnostic verbosity with logLevel, update it with setLogLevel or the idiomatic equivalent, and send structured diagnostics to your observability system with onDiagnostic. Remove uses of createLogger, create_logger, NewLogger, logger handler options, and logger fields in SDK options.
The same runtime changes apply across the v3 SDKs:
- hooks are replaced by modules with
setup,beforeEvaluation,bucketKey,bucketValue,afterEvaluation, andcloselifecycle callbacks; setDatafilemerges supported datafile entities by default, with an explicit replace argument for the old behaviour;- sticky values are configured on the main or child instance instead of individual evaluations;
- diagnostics replace custom logger injection;
- child instances use a snapshot of the parent context and release delegated subscriptions when closed;
- explicit defaults preserve falsey and null values;
- regular expressions, dates, and semantic versions follow the same portable rules in every SDK;
- datafiles use schema version
2only.
The exact method names and callback types follow each language's conventions. Review the relevant SDK guide before upgrading and update code and tests together.
Global variable availability
Global variables are supported by the current JavaScript, Node.js, Browser, React, Vue.js, Go, Swift, Java, Kotlin, Ruby, Python, PHP, Rust, and Elixir SDKs. Upgrade every application to a release that explicitly includes this support before publishing datafiles that rely on global variables.
React and Vue SDK usage#
The React and Vue packages now expect the renamed createFeaturevisor function and Featurevisor type. Update any provider, application setup, or utility code that imports the old factory or type.
The React provider still receives an already-created instance:
import { createFeaturevisor } from '@featurevisor/sdk'import { FeaturevisorProvider } from '@featurevisor/react'const f = createFeaturevisor({ datafile: datafileContent })root.render( <FeaturevisorProvider instance={f}> <App /> </FeaturevisorProvider>,)If an older Vue setup still passes datafileUrl, fetch the datafile before creating the instance instead:
import { createInstance } from '@featurevisor/sdk'const f = createInstance({ datafileUrl: DATAFILE_URL,})import { createFeaturevisor } from '@featurevisor/sdk'const datafile = await fetch(DATAFILE_URL) .then(response => response.json())const f = createFeaturevisor({ datafile })The Vue package no longer ships useStatus or activateFeature. To track exposure, register a module that reacts to evaluations in its afterEvaluation callback.
Learn more in React SDK and Vue.js SDK pages.
Migration checklist#
Use this order for each existing project:
- Upgrade
@featurevisor/cliand declare environments explicitly when needed. - Move split environment files back into feature definitions, or model independent trees as sets.
- Convert every scope into a target and add at least one target for building datafiles.
- Decide whether to keep slash-separated namespace keys or migrate application and test references to dots.
- Review multi-child
segments.notexpressions and remove empty logical arrays. - Update regex flags and date conditions to the portable formats.
- Replace assertion
scopeandtagfields withtarget, then run the complete test suite. - Build and inspect every target and environment datafile before publishing it.
- Update Catalog, promotion, code-generation, and CI commands and output paths used by automation.
- Upgrade each application SDK, update factory and type names, and replace logger and hook integrations.
- Review
setDatafile, sticky ownership, child cleanup, module cleanup, explicit defaults, and removed helper imports in application code. - Run application tests against the same v3-generated datafiles that will be deployed.
The project and application upgrades can remain separate deployments as described at the start of this guide.

