Skip to main content

dagster-malloy

dagster-malloy is an unofficial community integration library providing Dagster support for Malloy models (.malloy) and notebooks (.malloynb).

Features

  • Malloy as Dagster assets: Expose Malloy queries, dashboards, and notebooks as Dagster assets including rich metadata (compiled SQL, DDL, Malloy source code, column schema, row preview, code references, and execution duration).

  • Warehouse-Native Materialization (CTAS/CVAS): Execute compiled Malloy models directly inside target database warehouses (DuckDB, BigQuery, Snowflake, Postgres, Redshift) via CREATE TABLE / VIEW AS <compiled_sql> using Dagster database connection resources. Eliminates data egress and Python RAM bottlenecks.

  • In-Memory DataFrame Pattern: Optionally stream or load small-to-medium query results as Polars DataFrames into Python for downstream machine learning or custom Python data assets.

  • Complete data lineage: Automatically resolve Malloy source dependencies — including joined sources — to build a complete asset graph visible in the Dagster UI.

  • Data quality checks: Write validation queries directly in Malloy and have them run automatically as Dagster asset checks — either inline during asset materialization or as standalone check definitions. In warehouse mode, checks run directly against database connections in milliseconds.

    # Verify Customer IDs are non-null
    query: check_valid_customer_ids is orders -> {
      where: customer_id is null
      aggregate: invalid_count is count()
    }
    

Dagster Asset Lineage Graph

Quickstart

Try dagster-malloy using:

uvx dagster-malloy-demo

This generates a sample project (./malloy_demo) and launches the Dagster UI at http://127.0.0.1:3000.

Installation

uv add dagster-malloy

Usage

1. Warehouse-Native Materialization (Recommended for Production & ELT)

Use execution_mode="warehouse" to compile Malloy queries into dialect-optimized SQL and execute CREATE TABLE / VIEW AS <sql> directly in your warehouse using Dagster database resources (DuckDBResource, BigQueryResource, SnowflakeResource):

from pathlib import Path
from dagster import Definitions
from dagster_duckdb import DuckDBResource
from dagster_malloy import load_malloy_assets, MalloyResource

# Materializes Malloy queries as tables directly in DuckDB warehouse
malloy_table_assets = load_malloy_assets(
    path=Path(__file__).parent / "models",
    execution_mode="warehouse",
    materialization_mode="table", # "table" (CTAS) or "view" (CVAS)
    db_resource_key="duckdb",
)

defs = Definitions(
    assets=[malloy_table_assets],
    resources={
        "malloy": MalloyResource(execution_mode="warehouse"),
        "duckdb": DuckDBResource(database="data/warehouse.duckdb"),
    },
)

2. Loading Malloy Assets (In-Memory / Auto Mode)

Use load_malloy_assets in auto mode for local development or Python data assets. Queries are executed and returned as polars.DataFrame:

from pathlib import Path
from dagster import Definitions
from dagster_malloy import load_malloy_assets, MalloyResource

malloy_assets = load_malloy_assets(
    path=Path(__file__).parent / "models",
    include_checks=True,  # Default: True (registers inline asset checks)
)

defs = Definitions(
    assets=[malloy_assets],
    resources={
        "malloy": MalloyResource(cli_path="npx malloy-cli"),
    },
)

3. Using MalloyProject

Use MalloyProject to manage project paths, manifest location, and dev auto-compilation in a single object:

from pathlib import Path
from dagster_malloy import MalloyProject, load_malloy_assets

project = MalloyProject(
    path=Path(__file__).parent / "models",
    manifest_path=Path(__file__).parent / "models" / "malloy_manifest.json",
    auto_recompile_if_stale=True,  # Default: True
)

malloy_assets = load_malloy_assets(project=project)

4. AST Manifests & Serverless / Python-Only Deployments

In production or serverless environments (Cloud Run, ECS, Kubernetes), you can eliminate 100% of the Node.js runtime dependency for loading Dagster asset definitions by pre-compiling an AST manifest during CI/CD or Docker build.

Building the Manifest (CI/CD / Dockerfile):

Use the dagster-malloy build-manifest CLI command:

# Pre-compile Malloy AST metadata into analytics/malloy_manifest.json
dagster-malloy build-manifest analytics/ --output analytics/malloy_manifest.json

Loading Pre-compiled Manifests:

When malloy_manifest.json exists alongside your models (or when manifest_path is explicitly passed), dagster-malloy loads asset definitions in pure Python (< 1ms) without calling Node.js.

malloy_assets = load_malloy_assets(
    path=PROJECT_ROOT / "analytics",
    manifest_path=PROJECT_ROOT / "analytics" / "malloy_manifest.json",
    use_manifest_if_exists=True,
)

5. Execution Modes Configuration

dagster-malloy supports three execution engine modes via MalloyResource or load_malloy_assets:

  • "warehouse": Compiles query to SQL and executes CREATE TABLE/VIEW AS <sql> directly via Dagster database resource. Zero data egress to Python.
  • "cli": Executes query via malloy-cli run --json and returns polars.DataFrame.
  • "auto" (Default): Resolves automatically to CLI or warehouse execution mode.
resource = MalloyResource(
    execution_mode="warehouse",
    cli_path="npx malloy-cli",  # Path to malloy-cli binary or npx
    config_path="path/to/malloy-config.json",  # Optional path to database connections config
    project_dir="path/to/project",  # Optional project root for relative file paths
)

6. Connection Config & Dialect Resolution (malloy-config.json)

dagster-malloy automatically resolves custom connection identifiers (e.g. orca.table(...)) to their underlying database engine (e.g. duckdb) to assign clean kind badges in the Dagster UI and enrich asset metadata:

  1. Automatic Config Discovery: dagster-malloy automatically discovers malloy-config.json in parent directories, or you can specify config_path:
    malloy_assets = load_malloy_assets(
        path="./models",
        config_path="./malloy-config.json",
    )
    
  2. Database Resource Fallback: In warehouse execution mode (execution_mode="warehouse"), passing db_resource_key="duckdb" provides an immediate fallback to infer the dialect and assign the appropriate kind badge without needing a malloy-config.json file.
  3. Lineage & Storage Metadata: Both sources and queries are enriched with standard metadata keys: malloy/connection, malloy/dialect, dagster/table_name, dagster/storage_kind, and database/schema details from connection configurations.

7. Custom Translator (MalloyTranslator)

Subclass MalloyTranslator to customize asset keys, tags, group names, metadata, or upstream dependencies:

from dagster import AssetKey
from dagster_malloy import MalloyTranslator, MalloyTranslatorData, load_malloy_assets


class CustomMalloyTranslator(MalloyTranslator):
    def get_asset_key(self, data: MalloyTranslatorData) -> AssetKey:
        return AssetKey(["analytics", data.query_info.name])

    def get_group_name(self, data: MalloyTranslatorData) -> str:
        return "malloy_models"


malloy_assets = load_malloy_assets(
    path="./models",
    translator=CustomMalloyTranslator(),
)

8. Data Quality Checks

Malloy check queries (starting with check_, test_, assert_ or annotated with # @check) are automatically registered as inline Dagster asset checks by default (include_checks=True).

Alternatively, use build_malloy_asset_checks to register standalone asset check definitions attached to a target asset:

from dagster import AssetKey
from dagster_malloy import build_malloy_asset_checks

checks = build_malloy_asset_checks(
    file_path="./models/sales.malloy",
    target_asset_key=AssetKey(["sales", "customer_analytics"]),
    execution_mode="warehouse",
    db_resource_key="duckdb",
)

A check passes when the query returns zero rows, or when the first row contains invalid_count = 0 or fail_count = 0.

Example Project

A self-contained runnable example project is available in dagster_malloy_demo demonstrating DuckDB warehouse CTAS materialization, view materialization, and parameterized queries.

To run the example locally:

git clone https://github.com/mathisdrn/dagster-malloy.git
cd dagster-malloy/dagster_malloy_demo
uv run generate_data.py
uv run dg dev -f definitions.py

Open http://127.0.0.1:3000 to view the asset catalog and lineage graph.

Contributing

Contributions, issues, and pull requests are welcome! Feel free to open an issue or submit a pull request on GitHub.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dagster_malloy-0.2.7.tar.gz (708.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dagster_malloy-0.2.7-py3-none-any.whl (398.0 kB view details)

Uploaded Python 3

File details

Details for the file dagster_malloy-0.2.7.tar.gz.

File metadata

  • Download URL: dagster_malloy-0.2.7.tar.gz
  • Upload date:
  • Size: 708.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for dagster_malloy-0.2.7.tar.gz
Algorithm Hash digest
SHA256 1e106fb093aaf47ad68bc360dad82aae1b16f1aad1acbb373817e205424cf99f
MD5 1d72ba4d0c6296166c7a3f1ae713c7fd
BLAKE2b-256 9fb3c241a80f23c9d78c0d1fb3949a54ea98ba70a8417bc0d58c80fde8f6d0a2

See more details on using hashes here.

File details

Details for the file dagster_malloy-0.2.7-py3-none-any.whl.

File metadata

  • Download URL: dagster_malloy-0.2.7-py3-none-any.whl
  • Upload date:
  • Size: 398.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for dagster_malloy-0.2.7-py3-none-any.whl
Algorithm Hash digest
SHA256 e0e4a4f2caf88b006d0a90a538609ab6210620233a112fe541d7fbf7d744e4f9
MD5 dc5da2e72f26196f77efddae81451acf
BLAKE2b-256 bbea63545558a75be9f7731e5d2cc5f727c4babdcbb257e55563d7bd9b19af33

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.7 This release

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.1

2 files

0.2.0

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page