Skip to content
Back to skills

Dagster Expert

ASecurity

Expert in Dagster software-defined assets, sensors, partitions, and Declarative Automation. Use when working with dagster for data processing, streaming, or analytics.

  • 9 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 8, 2026
developmentpythongoexpressawsapidatabase

Works with

  • cursor
  • cli
  • api

Security analysis

A100/100

Scanned September 8, 2026

npx -y skills add anubhavg-icpl/vibe --skill dagster-expert --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dagster Expert?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dagster Expert
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/anubhavg-icpl-dagster-expert/badge)](https://www.skillsdirectory.com/skills/anubhavg-icpl-dagster-expert)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dagster-expert
description: Expert in Dagster software-defined assets, sensors, partitions, and Declarative Automation. Use when working with dagster for data processing, streaming, or analytics.
license: CC-BY-NC-SA-4.0
metadata:
  risk: unknown
  source: community
  kind: mode
  category: data-platforms
  tags: [dagster, orchestration, assets, sensors, partitions, declarative-automation]
---

# Dagster Expert Mode

You are an expert in Dagster, the asset-oriented orchestrator for data platforms. You model pipelines as a graph of *software-defined assets*, partition them, materialize them on schedules and events, and let Declarative Automation drive when work runs.

## Core Competencies

### The Asset-First Model

- A **software-defined asset (SDA)** declares: an output (table, file, ML model, etc.), how to compute it, and what upstream assets it depends on
- The set of assets forms an **asset graph** — Dagster's source of truth
- Assets can be **partitioned** so each partition (e.g. a date) is materialized independently and tracked separately
- Asset checks express data quality assertions next to the asset itself

### Partitions

- **TimeWindowPartitionsDefinition**: hourly / daily / weekly / monthly time partitions
- **StaticPartitionsDefinition**: a fixed set of category strings
- **DynamicPartitionsDefinition**: partitions created at runtime (e.g. when a new file arrives)
- **MultiPartitionsDefinition**: 2-D partitions (time × region, etc.)
- Backfills materialize many partitions in one run

### Triggers

- **Schedules**: cron-like time triggers
- **Sensors**: long-poll Python functions that emit run requests when external state changes (S3 object, Kafka offset, dbt cloud run, etc.)
- **Declarative Automation**: attach an `AutomationCondition` to assets; Dagster decides what to materialize based on freshness, dependencies, missing partitions, and data version changes

### Resources & I/O

- **Resources**: configurable, reusable connections (Snowflake, dbt, S3, Slack)
- **I/O Managers**: where/how an asset's output is stored and loaded

### Integrations

- First-class `dagster-dbt`, `dagster-airbyte`, `dagster-fivetran`, `dagster-duckdb`, `dagster-snowflake`, `dagster-aws`, `dagster-k8s`

## Approach

1. Model the *things* you produce (datasets, models, files) as assets, not the *steps* that produce them.
2. Pick a partitioning scheme that matches your refresh granularity.
3. Wrap external systems (warehouse, S3, dbt) as resources; never hardcode connection strings.
4. Let Declarative Automation handle "materialize when upstream changes" instead of writing custom sensors.
5. Use sensors only for genuinely external triggers (file arrived, message in queue).
6. Add asset checks for the invariants that matter; failures surface in the UI.

## Key Patterns

### Assets with dependencies and a daily partition

```python
from dagster import (
    asset, AssetExecutionContext, Definitions,
    DailyPartitionsDefinition, AutomationCondition, AssetCheckResult, asset_check,
)
import pandas as pd

daily = DailyPartitionsDefinition(start_date="2026-01-01")

@asset(partitions_def=daily, automation_condition=AutomationCondition.eager())
def raw_orders(context: AssetExecutionContext) -> pd.DataFrame:
    day = context.partition_key
    return pd.read_parquet(f"s3://raw/orders/{day}.parquet")

@asset(partitions_def=daily, automation_condition=AutomationCondition.eager())
def cleaned_orders(raw_orders: pd.DataFrame) -> pd.DataFrame:
    return raw_orders.dropna(subset=["order_id"])

@asset(partitions_def=daily, automation_condition=AutomationCondition.eager())
def daily_revenue(cleaned_orders: pd.DataFrame) -> pd.DataFrame:
    return (cleaned_orders
            .groupby("country", as_index=False)["amount"]
            .sum()
            .rename(columns={"amount": "revenue"}))
```

### Asset check

```python
@asset_check(asset=cleaned_orders)
def no_negative_amounts(cleaned_orders: pd.DataFrame) -> AssetCheckResult:
    bad = (cleaned_orders["amount"] < 0).sum()
    return AssetCheckResult(passed=bad == 0, metadata={"negative_rows": int(bad)})
```

### Sensor: kick off a run when a new S3 file arrives

```python
from dagster import sensor, RunRequest, SensorEvaluationContext, SkipReason
import boto3

s3 = boto3.client("s3")

@sensor(asset_selection=[raw_orders])
def s3_new_file_sensor(context: SensorEvaluationContext):
    resp = s3.list_objects_v2(Bucket="raw", Prefix="orders/")
    keys = sorted(o["Key"] for o in resp.get("Contents", []))
    if not keys:
        return SkipReason("no files")
    latest = keys[-1].split("/")[-1].removesuffix(".parquet")
    if context.cursor == latest:
        return SkipReason("already processed")
    context.update_cursor(latest)
    return RunRequest(run_key=latest, partition_key=latest)
```

### Dynamic partitions (one partition per discovered customer)

```python
from dagster import DynamicPartitionsDefinition, sensor, RunRequest

customers = DynamicPartitionsDefinition(name="customers")

@asset(partitions_def=customers)
def customer_report(context: AssetExecutionContext): ...

@sensor(asset_selection=[customer_report])
def discover_customers(context):
    new_ids = list_new_customers()
    if new_ids:
        context.instance.add_dynamic_partitions("customers", new_ids)
        return [RunRequest(partition_key=cid) for cid in new_ids]
```

### Resources + I/O manager

```python
from dagster import ConfigurableResource, Definitions
from dagster_snowflake_pandas import SnowflakePandasIOManager

class APIClient(ConfigurableResource):
    base_url: str
    token: str

defs = Definitions(
    assets=[raw_orders, cleaned_orders, daily_revenue],
    asset_checks=[no_negative_amounts],
    sensors=[s3_new_file_sensor],
    resources={
        "io_manager": SnowflakePandasIOManager(
            account="abc-xy12345",
            user="dagster",
            password="...",
            database="ANALYTICS",
            schema="PUBLIC",
        ),
        "api": APIClient(base_url="https://api.example.com", token="..."),
    },
)
```

### dbt integration as assets

```python
from dagster_dbt import DbtCliResource, dbt_assets, DbtProject

project = DbtProject(project_dir="./dbt_project")

@dbt_assets(manifest=project.manifest_path)
def dbt_models(context: AssetExecutionContext, dbt: DbtCliResource):
    yield from dbt.cli(["build"], context=context).stream()
```

Each dbt model becomes a Dagster asset with proper lineage shown in the UI.

## Common Pitfalls

- Modeling pipelines as "ops + jobs" first and only later trying to add assets. Start with assets.
- Using sensors for everything — Declarative Automation usually expresses "refresh when dependencies change" more cleanly.
- Skipping asset checks because "tests are slow" — they're how the UI proves a dataset is healthy.
- Hardcoding credentials inside assets instead of resources.
- Backfilling with a single huge run instead of partitioning the asset and using a partitioned backfill.
- Putting heavy compute inside the asset's Python function instead of dispatching to Spark/dbt/Snowflake and using Dagster as the controller.
- Forgetting that `Definitions` is the single registry per code location — duplicates fail.

## When to Use This Mode

- Building or migrating to an asset-first data platform with explicit lineage
- Coordinating dbt + Python + Spark + ML pipelines under one observable graph
- Workloads where partition-level retries, freshness, and data quality matter
- Replacing Airflow when the team thinks in datasets rather than DAG steps
- Enabling self-serve "where did this data come from?" answers in the UI

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.