Blog
Orchestration is More than Scheduling: Declarative Automation in Dagster

Orchestration is More than Scheduling: Declarative Automation in Dagster

August 6, 2026
Orchestration is More than Scheduling: Declarative Automation in Dagster
Orchestration is More than Scheduling: Declarative Automation in Dagster

Define the outcome, not the orchestration. Declarative Automation lets you express your desired asset state while Dagster continuously handles the work needed to achieve it.

Modern data platforms aren't just collections of independent cron jobs; they are graphs of hundreds of interconnected assets, each with unique freshness requirements, partitioning schemes, and downstream consumers. The real challenge isn't deciding when code should run, it's deciding what actually needs to run.

Traditional schedulers are excellent at launching work on a fixed cadence, but they're less effective at continuously answering questions like:

  • Which assets are stale?
  • Which downstream assets require recomputation?
  • Which partitions are ready to materialize?
  • Which assets must wait for their dependencies?

As platforms grow, this orchestration logic often becomes scattered across schedules, sensors, cross-job triggers, and custom code, making systems increasingly difficult to understand and maintain.

Declare the goal, not the schedule

Dagster fully supports traditional orchestration patterns, including schedules and sensors, when they're the right tool for the job. Declarative Automation offers a different approach for problems that are better expressed as desired state.

Instead of imperatively describing when work should run, you declare what it means for an asset to be up to date. Dagster's automation daemon continuously evaluates those conditions against the live state of your asset graph, its dependencies, partitions, data versions, and execution state, and determines exactly what work needs to run.

Rather than hand-authoring an ever-growing collection of schedules and triggers, you describe the desired state of your data platform, and Dagster continuously works to bring it into that state.

Common automation policies, one declarative model

In Dagster, data pipelines are modeled as assets: datasets, tables, machine learning models, or other persistent outputs together with the code that produces them. Assets form a graph that captures how data flows through your platform and how each asset depends on the others.

Declarative Automation builds on that asset graph. You attach an automation condition directly to an asset, describing what it means for that asset to be considered up to date. Dagster continuously evaluates those conditions against the current state of the graph and requests work whenever an asset no longer satisfies its declared policy.

The built-in automation conditions cover many of the most common orchestration patterns:

import dagster as dg

# Update as soon as any upstream dependency changes — event-driven propagation.
@dg.asset(deps=["upstream"], automation_condition=dg.AutomationCondition.eager())
def eager_asset() -> None: ...

# Update once per cron tick, but only after all upstream deps have refreshed.
@dg.asset(deps=["upstream"], automation_condition=dg.AutomationCondition.on_cron("@hourly"))
def hourly_asset() -> None: ...

# Fill anything that's missing, without re-running what already exists.
@dg.asset(deps=["upstream"], automation_condition=dg.AutomationCondition.on_missing())
def backfill_asset() -> None: ...

These aren't separate systems; they are different ways to define an asset's 'up to date' state. For example, on_cron() isn't just a simple schedule. Each time the cron triggers, Dagster evaluates the asset graph state. It only requests the asset if upstream dependencies are ready; if not, it waits. Time becomes one input among many, including dependency state, partitions, and freshness.

Whether you prefer traditional schedules and sensors or choose Declarative Automation for part of your platform, both approaches work together within the same orchestration system. Declarative Automation simply gives you a higher-level way to express orchestration policies when your goal is to describe the desired state rather than manually coordinate execution.

Declarative automation shines with partitions

Partitioned assets are where Declarative Automation becomes especially powerful. In imperative orchestration systems, engineers often end up writing custom logic to answer questions like:

  • Which partitions are ready to process?
  • How do hourly partitions map to daily partitions?
  • Which downstream partitions should run next?
  • How do we avoid reprocessing work that's already complete?

With Declarative Automation, you don't encode that orchestration logic yourself. Instead, automation conditions are evaluated independently for each partition, and Dagster determines exactly which partitions need to be materialized.

import dagster as dg

@dg.asset(partitions_def=dg.HourlyPartitionsDefinition("2025-01-01-00:00"))
def upstream() -> None: ...

@dg.asset(
    deps=[upstream],
    automation_condition=dg.AutomationCondition.on_missing(),
    partitions_def=dg.DailyPartitionsDefinition("2025-01-01"),
)
def downstream() -> None: ...

Here, the upstream asset is partitioned hourly while the downstream asset is partitioned daily. Rather than manually tracking when all 24 hourly partitions for a given day have arrived, on_missing() simply declares the desired outcome: every daily partition should exist.

Dagster uses its understanding of the asset graph and partition mappings to determine when enough upstream data is available to produce each daily partition. Once that condition is met, it requests the partition exactly once.

You aren't describing how to coordinate hourly and daily partitions, just the desired state. This model scales seamlessly: whether you are dealing with differing partition granularities, dynamic partitions, or evolving dependency graphs, the same declarative logic applies without requiring extra orchestration code.

Composing automation policies

Real-world orchestration rarely comes down to a single trigger. An asset might need to refresh every five minutes, but only if new data has arrived. Or it might run immediately when an upstream dependency updates, unless another dependency is still materializing.

Rather than scattering this logic across multiple schedules, sensors, and trigger callbacks, Declarative Automation lets you express it as a single policy by composing automation conditions with logical operators.

import dagster as dg

5min_cron = dg.AutomationCondition.newly_updated().since(
    dg.AutomationCondition.on_cron("*/5 * * * *")
)

custom_condition = dg.AutomationCondition.on_cron("*/5 * * * *") | (
    dg.AutomationCondition.any_deps_updated()      # when any dependency updates
    & 5min_cron                                # and it changed since the last tick
    & ~dg.AutomationCondition.any_deps_missing()   # but not if deps are missing
    & ~dg.AutomationCondition.any_deps_in_progress()  # and not mid-run
)

@dg.asset(automation_condition=custom_condition, deps=["upstream_1", "upstream_2"])
def combined_asset(context: dg.AssetExecutionContext): ...

This policy can be read almost like English:

  • Run every five minutes.
  • Or run sooner if an upstream dependency has been updated since the last cron tick.
  • But don't run if dependencies are missing or currently materializing.

The important idea isn't the specific expression, it's that the orchestration policy lives in one place alongside the asset it governs. Instead of coordinating multiple schedules and sensors that interact with one another, you define a single declarative expression that captures the desired behavior.

Sometimes, however, the unit of orchestration isn't an individual asset. You may want a collection of assets to execute together in a single run, for example, when generating a report or publishing a coordinated dataset.

For those cases, job-level automation conditions (currently in preview) apply the same declarative model to an entire asset job:

analytics_job = dg.define_asset_job(
    "analytics_job",
    selection=[processed_data, report],
   automation_condition=dg.AutomationCondition.all_job_root_assets_match(
        dg.AutomationCondition.eager()
    ),
)

When the wrapped condition becomes true for the job's root assets, Dagster launches a single run for the entire job. The policy itself doesn't change, you simply choose whether it should govern an individual asset or a larger unit of work.

Test your logic before it hits production

Automation policies are application logic, and like any other application logic, they should be tested before they're deployed.

evaluate_automation_conditions() lets you evaluate automation policies against an ephemeral Dagster instance, making it easy to verify exactly what work would be requested without running the automation daemon.

def test_eager_condition():
    instance = dg.DagsterInstance.ephemeral()

    result = dg.evaluate_automation_conditions(defs=[upstream, downstream], instance=instance)
    assert result.total_requested == 0

    dg.materialize([upstream], instance=instance)

    result = dg.evaluate_automation_conditions(
        defs=[upstream, downstream], instance=instance, cursor=result.cursor
    )
    assert result.total_requested == 1

This test verifies that materializing the upstream asset causes exactly one downstream asset to be requested.

The same approach works for more sophisticated policies, including partitioned assets, cron-based conditions, and composed expressions. Rather than waiting for a scheduler tick or deploying the automation daemon, you can evaluate your policies in isolation and verify that they behave as expected.

Because automation conditions are deterministic expressions over the state of your asset graph, they can be unit tested just like the rest of your application code. As your orchestration logic grows more sophisticated, having fast, repeatable tests makes it easier to evolve your automation policies with confidence.

A different approach to orchestration

Data platforms are dynamic; dependencies evolve and data arrives unpredictably, making imperative scheduling difficult. Declarative Automation solves this by focusing on the desired state of assets rather than execution paths. While traditional schedules remain useful for specific integrations, Declarative Automation provides a simpler, more resilient way to express orchestration policies. Instead of maintaining a complex network of triggers, you simply define what 'up to date' means and let Dagster handle the rest.

Have feedback or questions? Start a discussion in Slack or Github.

Interested in working with us? View our open roles.

Want more content like this? Follow us on LinkedIn.

Dagster Newsletter

Get updates delivered to your inbox

Latest writings

The latest news, technologies, and resources from our team.

How we use AI to get to yes (and no!) 2x faster at Dagster
Webinar

July 9, 2026

How we use AI to get to yes (and no!) 2x faster at Dagster

Learn how Dagster uses AI to build custom demos that deliver a personalized experience for every customer.

Multi-Tenancy for Modern Data Platforms
Webinar

April 13, 2026

Multi-Tenancy for Modern Data Platforms

Learn the patterns, trade-offs, and production-tested strategies for building multi-tenant data platforms with Dagster.

Deep Dive: Building a Cross-Workspace Control Plane for Databricks
Webinar

March 24, 2026

Deep Dive: Building a Cross-Workspace Control Plane for Databricks

Learn how to build a cross-workspace control plane for Databricks using Dagster — connecting multiple workspaces, dbt, and Fivetran into a single observable asset graph with zero code changes to get started.

Orchestration is More than Scheduling: Declarative Automation in Dagster
Orchestration is More than Scheduling: Declarative Automation in Dagster
Blog

August 6, 2026

Orchestration is More than Scheduling: Declarative Automation in Dagster

Define the outcome, not the orchestration. Declarative Automation lets you express your desired asset state while Dagster continuously handles the work needed to achieve it.

Community Showcase Part 3
Community Showcase Part 3
Blog

July 30, 2026

Community Showcase Part 3

Some of the most interesting Dagster projects come from the community. This post highlights creative community-built applications.

Classifying a Million Snowflake Columns in 9 Days, Solo, with Dagster
Classifying a Million Snowflake Columns in 9 Days, Solo, with Dagster
Blog

July 16, 2026

Classifying a Million Snowflake Columns in 9 Days, Solo, with Dagster

data governance. I built a tiered AI classification system, human review workflow, and the Dagster orchestration that ties it all together in production in nine days.

Flo Energy's Data Platform for Critical Energy Data
Case study

August 4, 2026

Flo Energy's Data Platform for Critical Energy Data

Flo Energy transformed meter, weather, market, and strategy data into a unified, observable platform with Dagster.

How Magenta Telekom Built the Unsinkable Data Platform
Case study

February 25, 2026

How Magenta Telekom Built the Unsinkable Data Platform

Magenta Telekom rebuilt its data infrastructure from the ground up with Dagster, cutting developer onboarding from months to a single day and eliminating the shadow IT and manual workflows that had long slowed the business down.

Scaling FinTech: How smava achieved zero downtime with Dagster
Case study

November 25, 2025

Scaling FinTech: How smava achieved zero downtime with Dagster

smava achieved zero downtime and automated the generation of over 1,000 dbt models by migrating to Dagster's, eliminating maintenance overhead and reducing developer onboarding from weeks to 15 minutes.

Modernize Your Data Platform for the Age of AI
Guide

January 15, 2026

Modernize Your Data Platform for the Age of AI

While 75% of enterprises experiment with AI, traditional data platforms are becoming the biggest bottleneck. Learn how to build a unified control plane that enables AI-driven development, reduces pipeline failures, and cuts complexity.

Download the eBook on How to Scale Data Teams
Guide

November 5, 2025

Download the eBook on How to Scale Data Teams

From a solo data practitioner to an enterprise-wide platform, learn how to build systems that scale with clarity, reliability, and confidence.

Download the eBook Primer on How to Build Data Platforms
Guide

February 21, 2025

Download the eBook Primer on How to Build Data Platforms

Learn the fundamental concepts to build a data platform in your organization; covering common design patterns for data ingestion and transformation, data modeling strategies, and data quality tips.

AI Driven Data Engineering
Course

March 19, 2026

AI Driven Data Engineering

Learn how to build Dagster applications faster using AI-driven workflows. You'll use Dagster's AI tools and skills to scaffold pipelines, write quality code, and ship data products with confidence while still learning the fundamentals.

Dagster & ETL
Course

July 11, 2025

Dagster & ETL

Learn how to ingest data to power your assets. You’ll build custom pipelines and see how to use Embedded ETL and Dagster Components to build out your data platform.

Testing with Dagster
Course

April 21, 2025

Testing with Dagster

In this course, learn best practices for testing, including unit tests, mocks, integration tests and applying them to Dagster.