Windmill vs Airflow
Eight questions teams ask during a bake-off, with an honest answer on each one for where Windmill or Airflow is the better pick.

- 01What you can buildWhich solution fits for your specific use case
- 02TargetWho the platform is built for
- 03Build experienceHow you build on each platform
- 04IntegrationsHow the platform integrates with your existing stack
- 05Migration & lock-inHow hard to get in, how hard to get out
- 06Enterprise requirementsAudit logs, observability, security, performance
- 07Licensing & pricingOpen source, pricing, self-hosting
- 08VerdictThe verdict
An open-source workflow engine and developer platform to build and orchestrate all your internal software: scripts, workflows, data pipelines, AI agents and internal apps. Made for engineers who want full code flexibility and local dev experience, both to build internal software and to manage the underlying infrastructure.
Airflow in one sentenceAn open-source workflow orchestrator for data engineering. Python-native DAGs, 80+ provider packages for data-stack integrations, and a large ecosystem built up over a decade. Best for Python-literate data teams running scheduled ETL and ML pipelines.
Which internal software can you build and orchestrate?
Windmill is built to centralize and orchestrate all your internal software in one place. Scripts, workflows, data pipelines, full-code apps, AI agents and operator UIs run on a single runtime, with shared resources, auth and observability. Airflow focuses on workflow orchestration for data pipelines, so you bring your own stack for dashboards, internal apps and agent front-ends.
| Primitive | Airflow | |
|---|---|---|
Chain scripts into flows with branching, retries and approval steps | ||
ETL, syncs and scheduled data jobs with parallel branches | ||
Standalone functions exposed as APIs, webhooks or cron jobs without a wrapping workflow | ||
Build agents that call tools, branch on outputs and run as workflows | Partial | |
Isolated environments with persistent volumes for running agents | ||
Drag-and-drop dashboards and admin tools with built-in components | ||
Custom dashboards and admin tools built in React or Svelte | ||
Cron jobs with retries, error handling and alerting |
Who is each platform built for?
Windmill is built for developer-led teams who want one platform for scripts, workflows, data pipelines, apps and agents across multiple languages. Airflow is built for Python-literate data engineering teams running ETL and ML pipelines.
AirflowPrimary audience
Developer-led teams building any kind of internal software. Engineers own the platform end-to-end: code, Git, local dev, workspace forks, code review, CI/CD, AI coding tools, infrastructure as code. TypeScript, Python, Go, Bash, SQL and PHP are all first-class.
AirflowPython-literate data engineers running ETL and ML pipelines. A decade of community convention, books and tutorials is aimed at that persona. DAGs are Python files, and most integrations assume a Python runtime.
How non-developers participate
Non-developers consume through auto-generated UIs, custom apps and an operator role. They can build with AI assistance, but the experience is less optimized for them.
AirflowNon-developers can browse the DAG UI to monitor runs and trigger them manually. Authoring requires writing Python, so business users and analysts rarely edit DAGs directly.
How do you build on each platform?
Windmill gives you full code flexibility with a local dev loop and whole-workspace Git sync. Scripts, flows, apps, resources, permissions and infrastructure all live in Git like application code. Airflow is Python-native DAGs as Python files, with a mature tooling story built around that single language.
Compose steps visually as a DAG with branches, loops and approval steps directly in the Windmill UI. Each step is a real script in any of 20+ languages, edited and triggered in the same surface.
AirflowAuthoring
Build scripts in 20+ languages in a dedicated script editor. Each script is a standalone primitive with its own UI, API endpoint and scheduler; no wrapper required to run. Flows compose scripts into workflows with branching, retries and approval steps. Any public or private package is a first-class import with automatic dependency resolution.
AirflowDAGs are Python files placed in a dags/ folder and parsed by a scheduler. Tasks are built from operators (PythonOperator, BashOperator, provider-specific operators) or authored with the TaskFlow @task decorator. Data flows between tasks through XComs. Non-Python languages run as subprocesses inside a Python task.
Execution model
Two ways to define workflows, one runtime under both. The visual flow builder produces JSON DAGs with multi-language steps, transparent data passing via results.step_name expressions, and built-in branches, loops, error handlers and approval steps. Workflow-as-code defines the same flow programmatically in Python or TypeScript.
In the workflow-as-code engine, two step primitives carry different cost profiles. task() dispatches a child job in a separate process and surfaces as its own job in the UI, for steps that need isolation or independent retries. step() runs inline in the same process and checkpoints its result to Postgres in roughly 0.5ms, for cheap units like a calculation, a CSV parse or a small DB query. Each step picks the cost it actually needs.
AirflowDAGs are defined in Python. Every task is an independent execution unit: a trivial @task and a multi-minute job both go through the scheduler, executor and worker, with state transitions written to the metadata DB at each hop. The executor is pluggable (Local, Celery, Kubernetes), but the per-task overhead is fundamental to the model and is most visible on lightweight, high-volume workloads. The webserver renders DAGs (Graph, Grid, Gantt views) for monitoring, but authoring is Python-only.
Local dev & IDE
Author in the web editor with live runs and per-step logs, or edit the same scripts and flows locally with the Windmill CLI. VS Code extension, native language tooling (LSP, type-checking, linting) and AI coding tools (Claude Code, Codex). The loop is hot-reload: save a script, click run, see the result, including when adding a new dependency (resolved automatically per script, no worker restart).
AirflowNo in-browser editor: authoring happens in your IDE on files in the dags/folder. airflow standalone spins up a local scheduler, webserver and SQLite metadata DB for testing; the Astronomer astro CLI adds a Docker-based local dev loop. Standard Python IDE tooling applies to DAG files. The feedback loop has a few intrinsic delays: the scheduler re-parses DAG files on its own cadence (defaults to every 30s), so new or edited DAGs appear in the UI after that window. Installing a new package requires restarting the scheduler and workers. airflow tasks test <dag> <task> runs a single task in-process for tighter iteration without going through the scheduler.
Language runtimes
TypeScript (Deno, Bun, Node.js), Python, Go, Bash, SQL, PowerShell, PHP, Rust and more (20+ languages total). Any npm, PyPI, Go, Maven or Cargo package is a first-class import with automatic dependency resolution.
AirflowPython is first-class (PythonOperator, @task decorator). Other languages run through BashOperator or container-based operators (DockerOperator, KubernetesPodOperator). No native runtime for TypeScript, Go or other languages without wrapping them in a container.
Resources & secrets
Resources (typed JSON for credentials, connection info, configs) and Variables (individual secrets) are first-class and reusable across scripts, flows and apps. They're encrypted at rest, scoped via folders and groups for access control, and versioned in Git. External secret backends (Vault, AWS Secrets Manager) are Enterprise only.
AirflowConnections store credentials for external systems; Variables store configuration values. Both live in the metadata DB by default; external secret backends (Vault, AWS Secrets Manager, GCP Secret Manager) plug in via a config option.
Git & CI
Full IaC: scripts, flows, apps, resources, variables, secrets, schedules, folders, groups and permissions are all files in Git, deployed via the CLI and Git sync. Internal tooling runs like application code: PRs, reviews, rollbacks, CI/CD. Git sync is free for up to 2 users; beyond that is Enterprise only.
AirflowDAGs are Python files, so they version naturally in Git. Deployment depends on the environment: sync the dags/ folder to a shared volume, bake it into a Docker image, or use a vendor deployment command. Connections, variables and RBAC config usually live outside Git.
How does the platform integrate with your existing stack?
Windmill imports any public package (npm, PyPI, Go or Maven) as a first-class dependency with automatic resolution, and the authoring loop is hot-reload: save and run. Airflow ships a curated catalog of 80+ providers for mainstream data tools (Snowflake, dbt, Airbyte, Databricks) with managed connections and retries, and also lets you pip install any PyPI package into the worker for direct SDK calls from @task.
Type `import stripe` in the script editor and run. Windmill detects the import, resolves the version and pins it in a per-script lockfile automatically. No venv, no pip install, no restart: the platform manages dependencies for you.
AirflowConnecting out
Any npm, PyPI, Go or Maven package is a first-class import with automatic per-script dependency resolution and lockfiles, and no plugin layer in between: you call the vendor's real SDK with full type inference and auto-completion in the editor. 50+ pre-built resource types cover common databases (Postgres, Snowflake, BigQuery), SaaS (Slack, Stripe, GitHub, Notion, OpenAI) and infrastructure (S3, Redis, Kafka): paste an API key into a typed form and the resource is shared across scripts, flows and apps, encrypted at rest. A community Hub has reusable scripts and flows for common tasks.
AirflowTwo paths. A curated catalog of 80+ provider packages (AWS, GCP, Azure, Snowflake, BigQuery, dbt, Airbyte, Databricks, Slack and most data-stack tools) bundles typed operators, hooks and sensors with managed connections and retries. Or pip install any PyPI package into the worker environment and call its SDK directly from a @task, the same way you would in Windmill.
Receiving events
Native triggers for HTTP, cron, Kafka, NATS, Postgres CDC, SQS, MQTT, SMTP and WebSocket. Each trigger is a typed primitive in the UI: configure topic, subject or path, attach it to a script or flow, and Windmill handles the connection, replay and consumer-group state. Every script also gets an HTTP endpoint and a webhook URL for free, so most receive paths need zero glue code.
AirflowCron-style schedules, dataset-based triggering, sensors that poll external state, and HTTP webhook triggers via the REST API. Deferrable operators and the Triggerer handle event-like waits without holding a worker slot. No native Kafka or message-bus trigger; you build one with a deferrable sensor or operator.
Extending
A new integration is a script with a new import: save and run, no restart, no image rebuild. The loop is hot-reload all the way through, in the web editor, the CLI and Git sync. Custom logic can be exposed as a typed script, packaged as a resource type for shared use, or published to the private workspace Hub for the team.
AirflowCustom operator, hook or sensor as a Python class in plugins/ or a packaged provider. Authoring is straightforward; the friction is the deploy cycle: changes typically need a worker restart or an image rebuild before they pick up. Calling a Python library directly from @task sidesteps that and works for one-off logic.
How hard to get in, and how hard to get out?
Windmill keeps switching cost low. Step code is standard TS, Python, Go, Bash or SQL that runs anywhere, including after you leave Windmill. Airflow is a natural fit if your team already thinks in Python DAGs and plans to stay on the Airflow runtime.
AirflowGetting in
Paste a function body into the script editor, Windmill infers args, generates a UI, handles dependencies. No DAG boilerplate to learn. Triggers, schedules, variables and apps migrate one by one.
AirflowIf you already think in Python DAGs, onboarding is straightforward: add a file to thedags/ folder, set a schedule, pick operators. The learning curve is around Airflow-specific concepts (XComs, scheduler semantics, execution_date, catchup) and the operator catalog.
Getting out
Step logic is already standard code (TS, Python, Go, Bash, SQL) that runs anywhere. The CLI exports the full workspace as plain files. What you lose leaving Windmill is the runtime, not the step code.
AirflowTask bodies written in plain Python port cleanly to any Python runtime. Logic that depends on Airflow-specific primitives (XComs, sensors, dataset triggers, provider operators, Jinja templating on execution_date) needs rewriting against the new platform's equivalents.
Audit logs, observability, security, performance
Both cover the enterprise basics: RBAC, SSO, audit logs and observability. Windmill runs 40 lightweight Python tasks in 2.4s where Airflow takes 56s on equivalent hardware (around 23×), driven by single-hop worker dispatch instead of Airflow's scheduler, broker and worker chain. Airflow is built for long-running data tasks where per-task overhead is a rounding error, and enterprise features typically come from commercial vendors.
AirflowObservability
Real-time streaming logs, per-run inputs / outputs / duration, built-in worker queue metrics and a Prometheus exporter. Trace ID on every job.
AirflowPer-task logs, Gantt chart and grid view in the UI. StatsD and OpenTelemetry metrics for scheduler and worker health. Vendor-managed Airflow typically layers richer observability dashboards on top.
Audit logs
Full trail of who ran / edited / deployed what. Extended retention is Enterprise only.
AirflowBasic audit log of user actions in the UI. Longer retention and richer filtering are vendor features (Astronomer offers 7 days on Team, 90 days on Business). Vendor only.
Security
SOC 2 Type II compliant. RBAC, SSO (up to 10 users), encrypted secrets at rest and sandboxed script execution in open source. Uncapped SSO, audit logs and advanced access controls (SCIM, SAML) are Enterprise only.
AirflowBasic RBAC with predefined roles (Admin, Op, User, Viewer) in open source. SSO, custom RBAC, SCIM provisioning and SOC 2 / ISO certifications are supplied by commercial vendors like Astronomer or come from the underlying cloud (MWAA, Cloud Composer).Vendor only.
Multi-tenancy & isolation
Multiple isolated workspaces on the same instance, each with their own users, resources, secrets and access controls. Free tier is capped at 3 workspaces; unlimited is Enterprise only.
AirflowSingle-tenant by design in open source. Isolation between teams is usually achieved by running separate Airflow deployments per team. Multi-deployment management is a vendor feature. Vendor only.
Performance
Workers poll Postgres directly with SELECT ... FOR UPDATE SKIP LOCKEDand self-schedule. No separate scheduler process, no broker, no extra polling intervals on the dispatch path.
Cold start is around 12ms on Bun and 26ms on Python per job. Dedicated-worker mode Enterprise only keeps the runtime and dependencies pre-warmed for 0ms cold start. Arguments pass directly between steps, results are checkpointed as JSONB in Postgres with no built-in size limit.
AirflowThree-hop dispatch on the critical path: scheduler (polls the metadata DB, re-parses DAG Python files every few seconds, evaluates dependencies, checks pool limits) then DB state update, then broker (Redis or RabbitMQ for Celery), then worker. Every state transition is a DB write.
Cold start depends on the executor. LocalExecutor forks a subprocess per task that imports the full DAG file plus the Airflow framework (typically 1 to 2s). KubernetesExecutor spins up a fresh pod per task (10 to 30s). Data passes between tasks through XCom, serialized to shared storage with a 48KB default limit.
Open source, pricing, and self-hosting?
Windmill publishes upfront per-seat and per-worker Enterprise pricing, no sales call needed. Airflow's Apache 2.0 license is more permissive than Windmill's AGPLv3 for redistribution. Airflow has no direct proprietary tier; commercial features come from vendors like Astronomer.
AirflowOpen-source license
AGPLv3 core, free and unlimited self-hosted. Enterprise features (SSO, dedicated workers, audit logs, external secret backends) ship in a separate proprietary codebase. Managed cloud available.
AirflowApache 2.0, free and unlimited self-hosted. Airflow itself has no proprietary tier: commercial features (SSO, custom RBAC, managed infrastructure, higher-tier support) are delivered by third-party vendors like Astronomer, AWS MWAA and Google Cloud Composer.
Enterprise pricing
Enterprise adds SSO, audit logs, dedicated workers, advanced worker groups. Public per-seat and per-worker pricing on the pricing page.
AirflowAstronomer publishes hourly deployment and worker pricing for its Developer and Team tiers; Business and Enterprise tiers require a sales conversation. AWS MWAA and Google Cloud Composer bill as cloud infrastructure.
The verdict
Windmill and Airflow are both DAG-of-tasks orchestrators, but work moves through the engine in fundamentally different ways. Airflow models a workflow as Python files re-parsed by a scheduler that polls a metadata DB and dispatches tasks through an executor and a broker to workers. Windmill models a workflow either as a JSON DAG of multi-language scripts in the visual flow builder, or as workflow-as-code, with workers polling Postgres directly and a dual primitive that picks between dispatched child jobs and inline checkpointed steps.
Airflow can be a good fit if your team already thinks in Python DAGs, your workload is mainstream data-pipeline orchestration that its 80+ provider catalog already covers, and Apache 2.0 licensing of the core matters for redistribution. A decade of community convention, books and tutorials makes onboarding a Python-literate data engineer straightforward.
Windmill also works very well for those use cases, and goes considerably deeper. The developer experience covers 20+ first-class language runtimes with a local-dev loop, AI coding tools against real source files, and whole-workspace Git sync for scripts, flows, apps, resources and permissions. The runtime scope is wider too: the same platform that runs your workflows also powers data pipelines, AI agents and both low-code and full-code internal apps, with shared auth, secrets and observability across all of them. For short, high-volume workloads, Windmill runs around 23× faster than Airflow on equivalent hardware (40 lightweight Python tasks in 2.4s versus 56s), driven by single-hop worker dispatch instead of Airflow's scheduler, broker and worker chain. More of the enterprise foundation ships in open source, and Enterprise pricing is published upfront instead of gated behind a vendor sales call.
The switching cost is also asymmetric: Windmill step logic is standard code (TypeScript, Python, Go, Bash, SQL) that runs anywhere after you leave Windmill, while Airflow workflows built on provider operators, XComs, sensors and dataset triggers have to be rewritten on any other platform. If you're deciding between the two, the fastest way to judge is to spend an afternoon in each.
Frequently asked questions
Build your internal platform on Windmill
Scripts, flows, apps, and infrastructure in one place.