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, Malloy source code, column schema, row preview, code references, and execution duration).
-
Complete data lineage: Automatically resolve Malloy source dependencies — including joined sources — to build a complete asset graph visible in the Dagster UI.
-
Materialization: Queries are compiled and executed via
malloy-clior themalloyPython SDK. Results are surfaced as Apache Arrow, enabling zero-copy handoff to downstream assets. -
Data quality checks: Write validation queries directly in Malloy and have them run automatically as Dagster asset checks. Failed checks block downstream materializations, appear in the Dagster UI timeline, and are tracked in the asset health history — without any extra orchestration code.
# Verify Customer IDs are non-null query: check_valid_customer_ids is orders -> { where: customer_id is null aggregate: invalid_count is count() }
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. Loading Malloy assets
Use load_malloy_assets to discover and construct Dagster assets from .malloy files or .malloynb notebooks in a directory:
from pathlib import Path
from dagster import Definitions
from dagster_malloy import load_malloy_assets, MalloyResource
# Loads Malloy assets using pre-compiled manifest (if present) or dynamic Node.js parsing
malloy_assets = load_malloy_assets(
path=Path(__file__).parent / "models",
use_manifest_if_exists=True, # Default: True
)
defs = Definitions(
assets=[malloy_assets],
resources={
"malloy": MalloyResource(
cli_path="npx malloy-cli",
),
},
)
2. 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 to load_malloy_assets), 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", # Optional explicit path
use_manifest_if_exists=True, # Default: True
)
If Node.js is missing from $PATH and no manifest is available, dagster-malloy raises an explicit MalloyEnvironmentError with actionable instructions.
3. Execution configuration
dagster-malloy compiles and executes queries using malloy-cli / npx malloy-cli via MalloyResource:
resource = MalloyResource(
cli_path="npx malloy-cli", # Optional custom executable or path
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
)
4. 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(),
)
5. Data quality checks
Use build_malloy_asset_checks to discover check queries in a .malloy file and register them as Dagster AssetCheckResult checks 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"]),
)
A query is recognised as a check if it's name starts with check_, test_, assert_ (eg. query: check_valid_ids is ...) or if it's annotated with # @check, # @test or # @assert before the query definition.
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 with instructions to run locally.
To clone and 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dagster_malloy-0.2.0.tar.gz.
File metadata
- Download URL: dagster_malloy-0.2.0.tar.gz
- Upload date:
- Size: 735.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7047e74a3ea82af6895a7d83780d0deae9bc1e40fdb06c0a4c35a34d73ad5db
|
|
| MD5 |
5668ddc4b265ebc37785aa7a026de105
|
|
| BLAKE2b-256 |
3828f7f050f091c9ee6bba1f28649643b9a991949ddd690a1ed7b831f7961b0c
|
File details
Details for the file dagster_malloy-0.2.0-py3-none-any.whl.
File metadata
- Download URL: dagster_malloy-0.2.0-py3-none-any.whl
- Upload date:
- Size: 430.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a200aae2f7a2fe88c86f82eb1d2bb88364f0e2c600b5cd1978f354cfd57e88c
|
|
| MD5 |
652a1897129ea0ea7180aa9110069075
|
|
| BLAKE2b-256 |
cc0aeecd4cf51c3d1200426eff7925f788cde5e37270f4ab364f8c86166af567
|