Prototyping with lazy evaluation

FeatureQL evaluates features lazily: only features referenced in the SELECT clause (and their dependencies) are computed. Everything else is ignored. This makes prototyping fast — you can define features for multiple entities in a single query and explore them one at a time by changing what you select.

Exploring one entity at a time

Consider a query that defines features for both customers and orders. When you select only customer-related outputs, FeatureQL evaluates just those features and their dependencies:

FeatureQL
WITH
    -- Related to the customer
    CUSTOMER_NAME := TABLES.DIM_CUSTOMERS[name],
  	NUM_ORDERS_RELATED := RELATED(SUM(IF(ORDER_DATE>TIMESTAMP '2025-01-01', 1, 0)) GROUP BY TABLES.FCT_ORDERS[order_customer_id] VIA CUSTOMER_ID),
    -- Related to the order
    ORDER_DATE := TABLES.FCT_ORDERS[time_create]
SELECT
    -- Related to the customer
    CUSTOMER_ID,
  	NUM_ORDERS_RELATED,
    -- Related to the order
    -- ORDER_ID,
  	-- ORDER_DATE
FROM FM.ECOMM
FOR CROSS
    CUSTOMER_ID := BIND_VALUES(SEQUENCE(100,102)),
    ORDER_ID := BIND_VALUES(SEQUENCE(200,203)),
;
Result
FM.ECOMM.CUSTOMER_ID BIGINTNUM_ORDERS_RELATED VARCHAR
1002
1010
1021

The same query, with order-related outputs selected instead, evaluates only the order features:

FeatureQL
WITH
    -- Related to the customer
    CUSTOMER_NAME := TABLES.DIM_CUSTOMERS[name],
  	NUM_ORDERS_RELATED := RELATED(SUM(IF(ORDER_DATE>TIMESTAMP '2025-01-01', 1, 0)) GROUP BY TABLES.FCT_ORDERS[order_customer_id] VIA CUSTOMER_ID),
    -- Related to the order
    ORDER_DATE := TABLES.FCT_ORDERS[time_create]
SELECT
    -- Related to the customer
    -- CUSTOMER_ID,
  	-- NUM_ORDERS_RELATED,
    -- Related to the order
    ORDER_ID,
  	ORDER_DATE
FROM FM.ECOMM
FOR CROSS
    CUSTOMER_ID := BIND_VALUES(SEQUENCE(100,102)),
    ORDER_ID := BIND_VALUES(SEQUENCE(200,203)),
;
Result
FM.ECOMM.ORDER_ID BIGINTORDER_DATE VARCHAR
2002025-09-18T14:30:00
2012024-12-08T09:45:00
2022025-02-03T12:00:02
2032025-09-18T14:30:00

The definitions are identical in both cases — only the SELECT clause changes. This lets you iterate quickly: define everything you might need, then toggle outputs to explore different slices of the data.

Cleaning up after prototyping

Once you've settled on the features you need, remove unused definitions for clarity. A production query should only contain features that contribute to its output — leftover definitions add noise even though they don't affect performance.

Avoid accidental cross-joins

If you select features from multiple entities in the same query (e.g., both customer and order outputs), FeatureQL produces a cross-join between the entity key sets. This is rarely what you want. Keep each query focused on a single entity's outputs, and use RELATED() or EXTEND() to pull in data from other entities.

Last update at: 2026/03/18 16:18:57
Last updated: 2026-03-18 16:19:34