home
diamond Go Premium
Data Engineering Path  ·  Airflow
Apache Airflow Logo

Plugins — Extending the Airflow UI Itself

Packaging More Than Just Operators

The Custom Operators page (Module 03) already covered packaging reusable operators/hooks/sensors under a plugins/ folder. Airflow Plugins are the formal mechanism behind that folder — and they can add more than code reuse: custom menu links, entirely new UI views, and Flask blueprints served alongside Airflow's own pages.


The Simplest Plugin: A Menu Link

# plugins/demo plugin.py
from airflow.plugins_manager import AirflowPlugin

class DemoMenuPlugin(AirflowPlugin):
    name = "demo_menu_plugin"
    appbuilder_menu_items = [
        {
            "name": "Data Catalog",
            "href": "https://internal-wiki.company.com/data-catalog",
            "category": "Docs",
        }
    ]

Any .py file in the plugins/ folder defining a subclass of AirflowPlugin is picked up automatically. This one adds a link to an internal tool directly in Airflow's own top navigation — useful for pointing teams at a data catalog, a runbook wiki, or an internal dashboard without leaving the Airflow UI.

Requires a webserver restart
Unlike DAG files (picked up automatically by the DAG File Processor on its normal scan interval), plugin changes need the webserver restarted to take effect — the navigation menu and any custom views are built once at webserver startup, not re-scanned continuously.

Custom Operators, Hooks, and Sensors as a Plugin

from airflow.plugins_manager import AirflowPlugin
from my_company.operators.row_count_validator import RowCountValidatorOperator

class CompanyOperatorsPlugin(AirflowPlugin):
    name = "company_operators"
    operators = [RowCountValidatorOperator]

This is the same RowCountValidatorOperator built in Module 03 — declaring it through a Plugin (rather than just importing it directly in each DAG file) makes Airflow aware of it as a first-class extension, which matters for the macro/view registration below.

Custom Views and Macros

from airflow.plugins_manager import AirflowPlugin
from flask import Blueprint
from flask_appbuilder import BaseView, expose

class TeamDashboardView(BaseView):
    route_base = "/team_dashboard"

    @expose("/")
    def list(self):
        return self.render_template("team_dashboard/index.html")

class TeamDashboardPlugin(AirflowPlugin):
    name = "team_dashboard"
    appbuilder_views = [{
        "name": "Team Dashboard",
        "category": "Reports",
        "view": TeamDashboardView(),
    }]
    macros = [lambda: "some_reusable_jinja_helper"]

A full BaseView gives a plugin an entire new page inside Airflow's own UI shell (same nav bar, same auth) — the mechanism managed services like Astronomer use to add their own environment-specific pages alongside the stock Airflow UI.

Tip — most teams only ever need the menu-link and operator-packaging patterns
Full custom views are powerful but rare in practice - building and maintaining a Flask/Jinja UI inside Airflow is real ongoing engineering work. Most plugin usage in the wild is exactly the first two patterns on this page: a link to an existing internal tool, and packaging custom operators for reuse.
lock

This content is reserved for Premium Members.

Upgrade to Premium

Entity Details

Create New Item

help

Submit Technical Query

Have a question or run into an issue? Describe it below, upload an optional screenshot, and our engineering team will answer it!

image Attach image (optional)

Submit Feedback

build Free Developer Utility Free Tool
gavel

Privacy & Legal Disclaimer

1. Client-Side Browser Processing

All utility tools on DeepEngineerHub (including Image to PDF, Text Formatters, JSON Converters, and Encryptors) execute 100% locally within your client browser using WebAssembly and JavaScript. No uploaded images, text, or documents are transmitted, collected, or stored on remote servers.

2. Limitation of Liability ("As-Is" Provision)

Tools and services are provided free of charge for convenience and educational purposes "as-is" without warranties of any kind. DeepEngineerHub shall not be held liable for any data loss, formatting inconsistencies, or indirect damages resulting from tool usage.

3. Open Source & Third-Party Software

Certain utilities utilize open-source client libraries (such as jsPDF, Mermaid.js, Pyodide) licensed under MIT, Apache, or BSD open licenses. All intellectual property remains with their respective copyright holders.