Skip to content

Overview

Daedalus is a feature platform built around one idea: a feature service is a declarative contract that compiles to one pipeline — a DAG of engine-tagged operators — which the executor runs directly against your data sources. There is no copy step and no separate "skeleton" and "enrich" stages: just operators, each optimized at its own level.

Engines:
Ingestion — direct sources
No copy/download step
Feature Catalog
Declarative, Arrow-typed contracts
One pipeline — an operator DAG
No skeleton/enrich stages — just operators
ScanSQL
FilterSQL
JoinSQL
PIT JoinSQL
Rolling AggregateSQL
Arrow UDFSQL + Arrow UDF
Ray UDFPythonic
SinkSQL
Execution — per-operator engines
Each operator self-optimizes
Platform surfaces
One in-process API, many surfaces

One pipeline — an operator DAG. A feature service compiles to a single operator DAG. Each operator carries a declared engine, and optimization happens per operator (sub-operator level) — there is no global query planner.

Interact

Hover a layer for its description, and click an engine chip to highlight which operators run on it. Nodes link to the relevant section.

The layers

1. Ingestion — direct sources

Daedalus reads data in place. A feature view points its source at one of four backends and DuckDB reads it directly — there is no download/copy stage:

  • Postgres (read-only)
  • S3 Hive-partitioned Parquet
  • DuckLake tables
  • Snowflake (read-only)

See Data Sources.

2. Feature Catalog

YAML feature views resolve to Arrow-typed columns; a feature service is the column-level contract a model consumes. The service is what gets compiled. See Feature Catalog.

3. One pipeline — an operator DAG

A feature service compiles (daeda pipeline compile) into a single operator DAG. Each operator declares the engine it runs on. The vocabulary:

OperatorEngineRole
Scan / Filter / Projectsqlread + project a source relation
Joinsqlenrich the spine with static columns
PointInTimeJoinsqlstrict-< as-of lookups
RollingAggregatesqlwindowed point-in-time aggregations
ArrowUdfTransformsql_arrow_udfa vectorized Arrow UDF over a SQL column
RayUdfTransformpythonicdistributed Ray/Lance embedding compute
Sinksqlwrite the result

See Operator Pipeline and Training → Operators.

4. Per-operator optimization

Optimization is sub-operator level — each operator self-optimizes through its declared engine; there is no global query planner:

  • sql — composed into DuckDB SQL and pushed down to the source (the source optimizes its own scan/filter/join).
  • sql_arrow_udf — SQL produces a column, then a vectorized Arrow UDF (e.g. avg_pool) runs over Arrow batches.
  • pythonicdistributed Ray actors over Arrow batches and the Lance embedding store.

Across all of them, daedalus owns only three levers: lazy evaluation, work partitioning, batch streaming — Arrow-native throughout (see Compute Engine and Arrow-Native Design).

5. Platform surfaces

The executor is wrapped by surfaces that all reuse one in-process API — Dagster, a JSON-RPC control plane, an MCP server, the CLI, and an optional MLflow projection. See Platform Surfaces.

Design rule: no query optimizer

Sources (DuckLake / Snowflake / Postgres, and DuckDB over them) optimize the source-side query themselves. Daedalus deliberately has no LogicalPlanPhysicalPlan planner and no cost model — it composes pushdown-friendly SQL for the source layer and owns only the post-source compute layer (Arrow UDF + Ray UDF), governed by lazy / partition / stream. This keeps the pipeline a thin, predictable, per-operator-optimized DAG.

Where to go next