Feature lifecycle
Every feature carries a status that says how much you should trust it: DEV, BETA, ACTIVE, DEPRECATED, or HARD_DEPRECATED. The interesting part is that status is not a label — the registry enforces it across the dependency graph, so a stable feature can never quietly be built on something half-finished.
This page follows one small feature and its consumer from first draft to retirement, and shows what the registry refuses along the way.
Lifecycle is a managed-registry capability. The local engine rejects status mutations and may expose STATUS as NULL.
Everything starts in DEV
Create two features — a basket value and a tax-inclusive version that depends on it.
CREATE OR REPLACE FEATURES AS
PERSIST
fm.tutorials.lifecycle.basket_value := 120,
fm.tutorials.lifecycle.basket_value_with_tax := fm.tutorials.lifecycle.basket_value
* 12
/ 10
;| feature_name VARCHAR | status VARCHAR | message VARCHAR |
|---|---|---|
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE | CREATED | Feature created as not exists |
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX | CREATED | Feature created as not exists |
Nothing was said about status, so both are DEV: usable, changeable, and not a promise to anyone.
CREATE OR REPLACE of a formula also resets the replaced feature to DEV and re-checks the same transition table and dependency matrix as ALTER FEATURE … SET STATUS. That is why an ACTIVE or BETA feature cannot be edited in place — a formula change is a new review, not a silent hotfix. Demote first, or introduce a replacement and retire the old name.
SHOW FEATURES (COLUMNS (NAME, STATUS)) WHERE NAME LIKE 'FM.TUTORIALS.LIFECYCLE.%';| NAME VARCHAR | STATUS VARCHAR |
|---|---|
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE | DEV |
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX | DEV |
Status is independent of descriptive metadata, custom attributes, and runtime quality assertions. An attribute named point_of_contact or pager_duty is documentation; it changes nothing about lifecycle behavior.
Promote from the bottom up
BASKET_VALUE_WITH_TAX looks ready for production, so try promoting it with ALTER FEATURE … SET STATUS.
ALTER FEATURE FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX SET STATUS = 'ACTIVE';The registry refuses, and the reason is the whole point of the feature: an ACTIVE feature may only depend on other ACTIVE features, and its dependency is still DEV. Promotion travels upward through the graph — dependencies first.
Promote both together and the pair is consistent, so it passes. ALTER FEATURES takes an explicit name list; mutation never accepts WHERE or LIKE.
ALTER FEATURES FM.TUTORIALS.LIFECYCLE.BASKET_VALUE, FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX
SET STATUS = 'ACTIVE';| feature_name VARCHAR | status VARCHAR | message VARCHAR |
|---|---|---|
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE | ALTERED | Feature successfully altered |
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX | ALTERED | Feature successfully altered |
BETA sits between the two: production-ready but still experimental, so it may depend on BETA and ACTIVE features and may be consumed by DEV and BETA ones. Use it when consumers should align with the point of contact before relying on the feature.
Retirement works the same way, in reverse
Months later the tax logic moves elsewhere and you want to deprecate BASKET_VALUE. Its consumer is still ACTIVE.
ALTER FEATURE FM.TUTORIALS.LIFECYCLE.BASKET_VALUE SET STATUS = 'DEPRECATED';Same rule, other direction: an ACTIVE feature may not depend on a DEPRECATED one. Retire the consumer along with it.
ALTER FEATURES FM.TUTORIALS.LIFECYCLE.BASKET_VALUE, FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX
SET STATUS = 'DEPRECATED';| feature_name VARCHAR | status VARCHAR | message VARCHAR |
|---|---|---|
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE | ALTERED | Feature successfully altered |
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX | ALTERED | Feature successfully altered |
DEPRECATED is a warning, not a wall — existing queries keep working.
RETURN
fm.tutorials.lifecycle.basket_value_with_tax
;| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX DOUBLE |
|---|
| 144 |
What it does stop is new work built on top of it. A fresh feature is created as DEV, and DEV may only depend on DEV, BETA, or ACTIVE.
CREATE OR REPLACE FEATURE FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_ROUNDED AS
ROUND(FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX);HARD_DEPRECATED is the wall
When the feature is genuinely gone, mark it HARD_DEPRECATED.
ALTER FEATURES FM.TUTORIALS.LIFECYCLE.BASKET_VALUE, FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX
SET STATUS = 'HARD_DEPRECATED';| feature_name VARCHAR | status VARCHAR | message VARCHAR |
|---|---|---|
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE | ALTERED | Feature successfully altered |
| FM.TUTORIALS.LIFECYCLE.BASKET_VALUE_WITH_TAX | ALTERED | Feature successfully altered |
Now every query that references it fails at compile time, which is how you find the last stragglers before deleting anything.
RETURN
fm.tutorials.lifecycle.basket_value_with_tax
;You cannot hard-deprecate a feature that is still referenced by a PREPARED_STATEMENT — remove the serving artifact first. Metadata edits such as SET DESCRIPTION still work on hard-deprecated features, so you can leave a note pointing at the replacement.
The rules in full
| Status | Production ready | What it means |
|---|---|---|
DEV | No | Default on create. In development, not ready for production. |
BETA | Yes | Production-ready but experimental. Can change at any time — align with the point of contact before using. |
ACTIVE | Yes | Stable features in production. |
DEPRECATED | Yes | Will be removed in the future. Cannot be used by new feature definitions that the dependency matrix forbids. |
HARD_DEPRECATED | Yes | Removed. Queries that reference it fail at compile time. Cannot be set while the feature is referenced by a PREPARED_STATEMENT. |
Both errors above come from one matrix, read in the two directions. A feature with status X can depend on:
| Status X | Can use features with status |
|---|---|
DEV | DEV, BETA, ACTIVE |
BETA | BETA, ACTIVE |
ACTIVE | ACTIVE |
DEPRECATED | ACTIVE, DEPRECATED |
HARD_DEPRECATED | HARD_DEPRECATED |
And a feature with status X can be depended on by:
| Status X | Can be used by features with status |
|---|---|
DEV | DEV |
BETA | DEV, BETA |
ACTIVE | DEV, BETA, ACTIVE, DEPRECATED |
DEPRECATED | ACTIVE, DEPRECATED |
HARD_DEPRECATED | HARD_DEPRECATED |
The rule applies to the dependency graph only — not to catalog position, namespace, or custom attributes.
Next
- Feature metadata — descriptions, attributes, display, position
- Units and measures — labelling what a numeric feature measures
- Metric additivity — dependency-safe rollup contracts and frontier changes