Registry consistency
Every mutation to the registry — create, replace, or drop — must leave the registry in a valid state. FeatureQL enforces this automatically: no permission level can bypass consistency checks, and any statement that would break the rules is rejected before it takes effect.
What FeatureQL validates
Valid function signatures — Every feature must use a function signature compatible with the types of its parameters. You cannot persist ADD(1, 'hello') because ADD doesn't accept a mix of integer and string arguments.
Dependency existence — All features referenced in a definition must exist in the registry. A feature cannot point to a dependency that hasn't been created yet or has been dropped.
No circular dependencies — The dependency graph must be a DAG (directed acyclic graph). If feature A depends on B, B cannot depend on A — directly or through any chain of intermediate features.
Type compatibility on replacement — When you replace a feature with CREATE OR REPLACE, FeatureQL checks that the new definition is compatible with all downstream features. If FEATURE3 calls ADD(FEATURE2, 1) and FEATURE2 is currently BIGINT, replacing FEATURE2 with a VARCHAR definition would break FEATURE3 — so FeatureQL rejects the replacement.
Type compatibility depends on how downstream features use the replaced feature. If every downstream feature casts the value to DOUBLE, then any type castable to DOUBLE is a valid replacement — not just the original type.
Lifecycle ordering (enterprise) — In environments with feature lifecycle management, a child feature (descendant) cannot have a higher lifecycle status than its parent features (dependencies). This prevents promoting a feature to production while its dependencies are still in development.
Drop protection
Features can only be dropped when no other features depend on them. Attempting to drop a feature with dependents produces an error identifying exactly which features need to be handled first:
Error: Cannot drop feature 'customer_age' because features ['lifetime_value', 'churn_risk'] depend on it. You can resolve this by either dropping the dependents first, including them in the same DROP statement, or wrapping everything in a transaction. See Drop features for details.
Why this matters
Strict consistency means you can trust the registry. If a feature exists, its entire dependency tree is valid and evaluable. There are no broken references, no type mismatches lurking in downstream features, and no silent failures at query time. The cost is that mutations require a bit more care — but the payoff is a registry that always works.