Filtering strategies
FeatureQL evaluates features for a set of input keys. How you select and filter those keys determines both the semantics and the performance of your query. There are two complementary approaches.
Precise key binding
Bind a specific set of keys using BIND_SQL() or BIND_KEYSET(). The query evaluates features for exactly those keys, regardless of what data exists in your tables:
CUSTOMER_ID := BIND_SQL(SELECT customer_id FROM customers WHERE registration_date > '2024-01-01') FeatureQL uses left join semantics when resolving data sources against bound keys. If a key has no matching data, the result is NULL rather than a missing row. This gives you explicit control: you always get one output row per bound key, and you can distinguish "no data" from "not requested."
Filter after binding
Alternatively, bind all available keys and then filter the results with a WHERE clause:
CUSTOMER_ID := BIND_KEYSET(AVAILABLE)
...
WHERE REGISTRATION_DATE > '2024-01-01' This approach feels more like standard SQL. FeatureQL applies predicate pushdown when possible, so filtering can be efficient. However, the result only includes keys that have matching data in the referenced data sources — there is no guarantee that all keys appear.
Choosing the right approach
| Scenario | Recommended approach | Why |
|---|---|---|
| Fixed key list (e.g., a cohort) | BIND_SQL() / BIND_KEYSET() | Explicit NULL handling for missing keys |
| Exploratory filtering | WHERE clause | Familiar syntax, natural filtering |
| Missing data matters | BIND_SQL() / BIND_KEYSET() | NULLs make missing data visible |
| Performance-critical | Test both | Key binding has join cost; WHERE uses predicate pushdown |
Key binding returns NULL for missing keys. WHERE filtering excludes them entirely. Be careful when using IS NULL in a WHERE clause — it cannot detect keys that were never bound.
Performance considerations
- Key binding incurs a left join between the bound keys and each data source. For small key sets against large tables, this is efficient. For very large key sets, the join itself can be costly.
- WHERE filtering avoids the join overhead and benefits from predicate pushdown when the filter aligns with data source partitions or indexes.
- FeatureQL pushes filters down in both approaches when possible. If performance matters, test both with your actual data volumes.