FAQ for the skeptical

If you have watched an ambitious data platform fail before, you are reading this looking for the catch. Fair. This page is for the person deciding whether FeatureMesh is a sound bet rather than a blocker that surfaces in month six.

Each answer here is short and standalone. Where the reasoning is longer than a paragraph, the link goes to the page that owns it.

The hard questions

Every DSL eventually forces you back to an escape hatch

The strongest objection on this page, and the one that has killed real projects. A limited language looks clean until real work hits what it cannot express. Everyone falls back to raw SQL, and you end up maintaining a leaky abstraction plus the SQL it failed to replace.

The answer is that the structure is constrained and the vocabulary is not.

FeatureQL is limited in scope, ordering, effects and types, on purpose. It is not limited in functions. There is a deep standard library (scalar, string, date, JSON, array, aggregate, window, statistical, geospatial), user-defined functions with a body per backend dialect, and macros. You rarely reach the wall.

When you do, the escape hatches are first class. UDFs extend the vocabulary. Hybrid queries let FeatureQL and ordinary SQL share one statement, so you drop to SQL for one piece without losing composition around it.

The test of a DSL is not whether an escape hatch exists. It is whether using it throws away what the language gave you. Here it does not.

What does the type system not check?

It proves what follows from declarations you make at the source, and nothing about the declarations themselves.

Grain is declared, not enforced. BIND TO names the lookup key, and two source rows with the same key fan out silently, because there is no primary-key check against the warehouse. DETERMINED BY is declared evidence, not a uniqueness scan. A false declaration produces a wrong answer that types correctly.

This is a consequence of the decoupling rather than an oversight. The compiler never reads your data, which is what lets one definition target three batch backends and a serving engine, and what keeps your rows out of our process. Verifying a key would mean querying the warehouse during compilation.

So the check moves to your side, as a test rather than as part of compilation. Data contracts lists each assumption. In the enterprise covers where to put the test.

And no contract encodes intent. A feature can carry the right entity, the right unit and the right additivity and still compute the wrong business rule.

Can a transpiler optimize as well as hand-written SQL?

Not always, and the page will not claim otherwise.

It applies consistent graph-level simplification and preserves dependency information. That does not guarantee the best physical plan for your data. Inspect the generated SQL and the backend plan for expensive workloads. An expert tuning against engine statistics can win.

The goal is a reliable baseline and explicit logic, not a universal claim of optimal SQL. If a specific workload comes out badly, hybrid SQL and UDFs let you hand-write that piece without giving up composition around it.

Nested data on a columnar warehouse: is that not slow?

For the common case, no. Intra-entity computation stays inside the array with TRANSFORM(). The default method is UNNEST. Cross-entity aggregation costs what it costs on your engine, the same as any SQL.

"Deterministic" is a strong word

It is enforced by the compiler rather than asserted. Non-deterministic functions (NOW(), RANDOM()) are a compile error unless you deliberately freeze them at compile time with @eval_as_literal(). External data enters only through declared EXTERNAL_* sources. Per-row randomness is hash-based and stable across runs.

What FeatureQL fixes is the value. Whether your engine evaluates a branch it did not select is your engine's decision. See No control flow .

Build versus buy: I do not want another black box, but I cannot rebuild this myself

This sits deliberately between the two. Buying a closed platform puts your business logic inside someone else's box, on their execution, with their exit costs. Building it yourself means years of internal plumbing before you ship anything.

The middle is: you own the logic in your registry and can inspect its dependency graph and generated SQL, while FeatureMesh supplies the composition engine, type system, cross-backend conformance and serving compiler. Execution stays on backends you operate.

The compiler and serving implementation are proprietary. Their inputs, diagnostics, definitions and generated batch SQL are inspectable. This is not an open-source compiler, and it is also not a system where extracting the batch logic requires reverse engineering.

How do I debug a deep composition?

Features transpile to flat CTEs in dependency order, so you can inspect any step. diagnose() executes the graph incrementally and stops at the first failing feature. validate() provides formatting, inferred output types and a backend preflight. If the logic is right but the data is wrong, swap in a controlled INLINE_COLUMNS source to isolate it.

The honest cost: when a query passes through the proxy and the transpiler, a failure sometimes means reading generated SQL next to the FeatureQL source. See Tools .

Will serving fall over at scale?

A prepared statement over a feature that aggregates a table per request is refused at registration. Serving is key lookup by enforcement, so its cost is proportional to keys fetched rather than table size, and the failure happens when you register the statement rather than under load.

Heavy aggregations are precomputed in batch and bound as a source. That precomputation is a job you run and schedule.

Scope and commitment

Why a language, and not another semantic layer?

Because configuration eventually reaches a composition boundary.

Several semantic layers build derived metrics from other metrics, so the distinction is not that they cannot compose. The boundary is what can be composed: usually metrics or models, under that system's relationship and aggregation rules. When a required calculation falls outside those rules, the gap is filled with hand-written SQL, and reuse becomes convention again.

FeatureQL makes any named calculation the unit of composition, carries entity, unit and additivity in the type system, and targets both batch and serving from one definition. That combination is the reason to take on a language at all. If deep composition and reuse is not a problem you have, the front page says so directly.

Which backends are supported today?

DuckDB and Trino for batch. Serving runs on DataFusion. Snowflake, Databricks, Redshift, PostgreSQL and Spark are not product backends today.

This is the first evaluation gate. Check it before modeling anything.

Is this only for large companies?

No. It runs from a pip install, and one person can use it in a notebook to organize calculations they keep rewriting. The value grows with the number of people who reuse those calculations.

The parts that need a platform team (shared registry, proxy, serving, materialization) are the parts you add when features become shared infrastructure. In the enterprise lists what each one costs to run.

Can anyone create features, or is it a bottleneck?

Anyone can, in their own namespace, and that is the point. The classic failure of a central semantic layer is a small team owning the definitions while everyone else waits in a queue.

Every change is validated against its downstream dependencies, so you can build locally without silently breaking someone else's feature. That protection is structural: a replacement that type-checks can still change a number, which is what regression tests are for.

Is this all or nothing?

No. You rewrite nothing to start. FeatureQL embeds inside regular SQL and connects through a transparent proxy, so you introduce one feature, use it in one query, and leave everything else untouched.

Your backends do not move, your existing SQL keeps working, and you adopt wherever the pain is worst.

How hard is it to try?

There is no procurement cycle. The pip package ships a local registry, and the optional featuremesh[serving] install adds an embedded DataFusion serving backend, so one engineer can prototype on a laptop with no account. Compilation, execution and help run without sending query text or row data to FeatureMesh. See the Python library setup .

When something is worth productionizing, the same features move to the managed registry. Nothing is rewritten between the two.

What happens to our logic if we stop using FeatureMesh?

Features compile to standard SQL you can read and retain, in flat CTEs in dependency order. Your definitions stay inspectable in the registry while you have it.

Read "readable" precisely: the output is not obfuscated, and it is not something anyone would choose to maintain by hand. Leaving means replacing registry governance, future compilation and the serving path, and that is not cost-free. What it does not mean is reverse engineering an executable blob.

Guarantees and their limits

"Same answer on every backend": real, or marketing?

Real, and precisely bounded. Three parts. Identical definitions everywhere. Identical behavior where the engines agree, with divergences (nulls, division, timezones, rounding) normalized in transpilation. A compile-time error naming the gap where a backend lacks a capability, such as RECURSE() outside DuckDB.

Never a silent cross-backend difference.

This is verified by an executable conformance suite you run yourself, and the documentation examples are those tests. It is tested equality over covered behavior, not a proof about an unsupported function, backend or business definition. Run the relevant corpus on day one.

What is the performance cost of adding a layer?

For batch, essentially none during SQL execution. FeatureMesh compiles a feature to SQL and your warehouse runs it. The scanning, joining and aggregating happen where they always did, on infrastructure you already tune.

Translation does add compile-time latency before the warehouse receives the SQL. Measure cold and warm compilation with your feature graphs if interactive latency matters.

Serving is the exception. Real-time features run on DataFusion, because a warehouse cannot serve at request latency. That is a real component you operate and should evaluate as one. A serving layer is not free and this page will not pretend it is.

Does it version features?

Live HEAD is still one current definition per name. Replacing a feature does not keep two current versions under that name. The managed registry also keeps an append-only FeatureQL changelog: DESCRIBE history, SHOW REVISIONS, AS OF a main revision, and implicit ON BRANCH overlays. Reconstruction is definitions-as-of today's compiler. Permissions and views are current-time. Approval is still a release process. Catalog revisions , Branch overlays .

Moving dependents to a successor is still a naming and release discipline you define. A type-compatible replacement can still change a number, so business logic changes are regression-tested with SLT (SQLLogicTest) files you write. Change management has the workflow around HEAD.

Who runs materialization for serving?

You do. A served feature cannot aggregate a table at request time, so heavy aggregations are computed in batch, written to a low-latency store, and bound as an EXTERNAL_* source.

FeatureMesh does not schedule that job and does not know when it last ran. Reimplementation drift between training and serving is gone. Staleness drift is yours to monitor.

AI

If AI writes the features, who checks they are right?

The real risk is not syntax. It is a feature that compiles, runs identically everywhere, and computes the wrong business concept. No type system removes that, so the design puts humans on exactly that question.

The shape is described in Deterministic core, model at the edges : the model composes from a small, typed, queryable vocabulary at one edge and explains results at the other, and everything between is compiled and executed deterministically. The model never writes a join and never sees a row.

What that buys is narrower failure modes and reviewable output, not correctness. Every persisted AI-authored feature is inspectable and dependency-tracked, and diagnostics plus flat-CTE inspection let a reviewer check intermediate values. Treat this as a design argument about where errors can occur, not as a measured error rate.

Can an AI run experiments on my customers unattended?

Mechanically, yes. VARIANT(), HASH01() and GRADUAL_ROLLOUT() are primitives an agent can drive, and the compiler will reject an invalid combination.

Commercially and legally, that is your release policy and not our claim. A variant can compile, run identically everywhere, and still cut a price by 40% for one segment or move a threshold in a way that correlates with a protected attribute.

The controls are yours to set: an allowlist of dependencies an agent may replace, a rollout cap, frozen metric definitions during an experiment, and a human gate for promotion to ACTIVE. FeatureMesh gives you the primitives and the audit trail. For regulated decisions the right amount of autonomy may be none. In the enterprise goes through each control.