Airflow 3 Plugin Development: DAG Dependencies
A step-by-step tutorial for building your first Airflow 3 plugin
Introduction
At Ponder, we’ve developed several plugins for Airflow 2.* and recently began migrating them to Airflow 3. Among our most valuable tools are Airflow Schedule Insights and Airflow Chat.
During the migration process, we discovered that Airflow 3.1.1 removed the DAG Dependencies tab that was present in Airflow 2.
Rather than wait for this feature to return, we saw an opportunity: we could build a plugin to restore this functionality, help the community migrate to Airflow 3 more smoothly, demonstrate how to create plugins for Airflow 3, and even add improvements we found missing in Airflow 2.
The result is airflow-dag-dependencies. In this post, we’ll walk you through how we built it and how it helps us manage our many educational DAGs.
Quick Start
To use our plugin, simply install airflow-dag-dependencies in your Airflow environment. If you don’t have an environment set up, clone our GitHub repository and run docker compose up.
After a few minutes, once Airflow is running, navigate to http://localhost:8080/ and log in with username “airflow” and password “airflow”. You’ll find a dozen educational DAGs — load_class_attendance, load_course_evaluations, and others.
Some are triggered by datasets, others by DAGs, and some run on cron schedules. The challenge? Understanding how they all connect.
This is where our plugin shines. Navigate to the Browse menu and click on DAG Dependencies.
You’ll immediately see all the relationships visualized clearly. Notice how transform_program_effectiveness has two dependencies: a cron schedule and a dataset trigger.
You can also spot that load_curriculum_catalog and load_student_enrollment_data have no dependencies or schedules—they won’t run automatically.
And you’ll see that transform_academic_performance is triggered by load_course_evaluations.
Enhanced Filtering
But we didn’t stop at recreating Airflow 2’s functionality—we added the filtering capabilities we always wished it had. Want to see only the direct downstream dependencies of transform_student_feedback_analysis and all its upstream dependencies? Simply enter +transform_student_feedback_analysis+1 in the search bar. The graph instantly filters to show only the relevant connections.
The search syntax is intuitive: use + before a DAG name to include upstream dependencies, after to include downstream, or both for the full picture. Add a number (like +dag_name+2) to control how many levels deep to traverse. You can also search multiple DAGs at once using commas, or use @exact_name for precise matching.
That’s the power of airflow-dag-dependencies!
Building Your First Airflow 3 Plugin: A Technical Deep Dive
Now that we’ve seen the plugin in action, here is how to build it from scratch. This walkthrough highlights the key differences between Airflow 2 and Airflow 3 plugin development and shows how to create your own plugin.
Plugin Structure: Airflow 3 vs Airflow 2
One of the most significant changes in Airflow 3 is how plugins are structured and registered.
Airflow 2 Plugin Structure
from airflow.plugins_manager import AirflowPlugin
from flask import Blueprint
from flask_admin import BaseView
class MyAirflow2Plugin(AirflowPlugin):
name = “my_plugin”
flask_blueprints = [my_blueprint] # Flask blueprints
admin_views = [MyAdminView] # Flask-Admin views
menu_links = [my_menu_link] # Menu itemsAirflow 3 Plugin Structure
from airflow.plugins_manager import AirflowPlugin
class MyAirflow3Plugin(AirflowPlugin):
name = “my_plugin”
fastapi_apps = [my_fastapi_app] # FastAPI applications
external_views = [my_external_view] # External view definitionsKey Changes in Airflow 3
• FastAPI replaces Flask for web applications, improving performance, async support, and automatic API documentation.
• External views replace Flask-Admin views, giving more flexible UI integration.
• Menu items are now part of external views rather than separate menu link definitions.
Anatomy of the DAG Dependencies Plugin
Package Structure
airflow_dag_dependencies/
├── __init__.py
└── plugins/
├── __init__.py
└── dags_dependencies_plugin.py
FastAPI Application
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get(”/”, response_class=HTMLResponse)
async def dag_dependencies_graph():
# Return HTML with embedded D3.js visualization
return html_content
@app.get(”/api/dag-dependencies”)
async def get_dag_dependencies():
# Return JSON data for DAG relationships
return {”nodes”: nodes, “links”: links}Plugin Registration
FastAPI app configuration
fastapi_app_with_metadata = {
“app”: app,
“url_prefix”: “/dags_dependencies”,
“name”: “DAG Dependencies App”
}External view for menu integration
dag_dependencies_external_view = {
“name”: “DAG Dependencies”,
“href”: “/dags_dependencies/”,
“destination”: “nav”,
“category”: “browse”,
“url_route”: “dag_dependencies”
}Plugin class
class DagDependenciesPlugin(AirflowPlugin):
name = “dags_dependencies_plugin”
fastapi_apps = [fastapi_app_with_metadata]
external_views = [dag_dependencies_external_view]Data Access: Using DagBag
The plugin accesses Airflow’s DAG metadata through DagBag.
from airflow.models import DagBag
async def get_dag_dependencies():
dagbag = DagBag(include_examples=False)
nodes = []
for dag_id, dag in dagbag.dags.items():
nodes.append({
“id”: dag_id,
“type”: determine_dag_type(dag),
“schedule”: get_schedule_info(dag)
})
links = analyze_dag_relationships(dagbag)
return {”nodes”: nodes, “links”: links}Frontend Options: Embedded or External
Airflow 3 supports multiple frontend approaches:
• Embedded HTML/JS (current plugin)
• Standalone React components (future tutorial)
• Serving static assets for more advanced UIs
Packaging for Distribution
Example pyproject.toml configuration:
[tool.poetry]
name = “airflow-dag-dependencies”
version = “0.1.1a1”
description = “An Apache Airflow plugin that provides interactive visualization of DAG dependencies”
authors = [”Ponder”]
[tool.poetry.dependencies]
python = “>=3.12, <3.14”
apache-airflow = “^3.1.0”
[tool.poetry.plugins.”airflow.plugins”]
dag-dependencies-plugin = “airflow_dag_dependencies.plugins.dags_dependencies_plugin:DagDependenciesPlugin”What’s Next?
The next tutorial will cover:
• Building React components that integrate with Airflow’s UI
• Handling authentication and permissions
Airflow 3’s FastAPI foundation opens the door to more capable, modern, and faster plugin development. More powerful integrations are now possible than ever.
Conclusion
Airflow 3 marks a real shift in how developers extend the platform. FastAPI, external views, and the new plugin model make it possible to build tools that are faster, more flexible, and much easier to maintain. Rebuilding the DAG Dependencies feature gave us a chance to explore these new capabilities in depth and turn a missing Airflow 2 feature into something more capable than before.
The airflow-dag-dependencies plugin restores a critical part of the Airflow UI, adds filtering and search features that help teams understand complex pipelines, and acts as a practical example of how to build real plugins in Airflow 3. If you are migrating from Airflow 2 or planning to develop your own extensions, this approach will give you a strong foundation.
There is still more room to grow. React-based UI components, richer interactions with Airflow’s new frontend APIs, and improved permission handling are all on the way. Airflow 3 opened the door to a modern plugin ecosystem, and this is only the start.








