Decoupled from execution

FeatureMesh is a compiler. It emits SQL text that a backend runs. There is no FeatureQL runtime in the batch path, and row data does not pass through FeatureMesh.

FeatureQL controls the SQL that is generated, so it determines types, dependencies and the value a feature computes. It does not control how the engine executes that SQL.

Readable output

Features compile to flat common table expressions (CTEs) in dependency order. Any intermediate step can be read and run by hand.

  • validate() returns the formatted query, the inferred types and a backend preflight, without scanning data.
  • diagnose() executes the graph one feature at a time and stops at the first failure.
  • INLINE_COLUMNS replaces a real source with a few known rows, to separate a logic problem from a data problem.

See Tools .

The same result across backends

Across DuckDB, Trino, and serving, the statement has three parts:

  1. The definitions are identical everywhere.
  2. Behavior is identical where the engines agree. Known divergences (nulls, division, time zones, rounding) are normalized in the generated SQL.
  3. Where a backend lacks a capability, compilation fails with an error that names it.

The set of available functions depends on the compilation target. DuckDB is the most complete. RECURSE(), for example, compiles on DuckDB and raises UE/FUNCTION-NOT-AVAILABLE RECURSE() on Trino and serving. The conformance suite runs the documentation examples on each backend.

Serving uses the same compiler

The same persisted feature compiles for serving. The SQL differs, since DataFusion has its own function names and struct syntax. The semantics and output types do not. The access path changes:

PathShapeSources
Batchaggregate over tablesEXTERNAL_COLUMNS FROM TABLE(...)
Servinglook up by keyEXTERNAL_REDIS, EXTERNAL_HTTP, JDBC VIEW(...)

A PREPARED_STATEMENT over a feature that aggregates a table is refused when it is registered (UE/RELATED-UNBOUND-INPUT). Serving cost is therefore proportional to the keys fetched, not to table size. Heavy aggregations are computed in batch, written to a key-value store, and bound as a source. What the two paths share is the definition of the business rule.

DataFusion is embedded in the serving process. It is a SQL target of the same compiler, and a component you operate.

No user interface

Existing SQL clients connect through a proxy that presents itself as Trino. FeatureQL embeds in ordinary SQL as FEATUREQL(...) blocks. A persisted view (FMV.schema.table) compiles a query once for tools that only speak SQL. A Python library covers notebooks, and a REST API covers serving.

Limits

  • The physical plan is the backend's. The compiler simplifies the graph, and manual tuning against engine statistics can still be faster on an expensive workload.
  • Compilation adds latency before the backend receives the SQL.
  • Behind the proxy, debugging can require reading the generated SQL next to the FeatureQL source.