Skip to main content

Modalflow

A serverless Airflow executor that runs tasks as Modal Functions.

Modalflow replaces Airflow's built-in executors (Local, Celery, Kubernetes) with one that dispatches each task to a Modal Function. No worker pools, no Kubernetes cluster, no infrastructure to manage — tasks run on-demand and scale to zero when idle.

Prerequisites

  • An existing Airflow 3.1+ deployment
  • A Modal account with the CLI configured (modal setup)
  • Python 3.10+

Setup

1. Install

Install modalflow on both your local machine (for the CLI) and your Airflow cluster (for the executor):

pip install modalflow

2. Deploy the Modal backend

The modalflow deploy command creates the Modal Function, Volume, and Dict that the executor needs. You must choose how DAG files are provided to the Modal task workers:

Local mode — bakes DAGs into the function image (simplest, but requires redeploying on every DAG change):

modalflow deploy --dags-source local --dags-path ./dags

Volume mode — stores DAGs on a Modal Volume (update DAGs without redeploying):

modalflow deploy --dags-source volume --dags-volume my-dags --dags-path ./dags

Cloud bucket mode — reads DAGs from an S3 bucket at runtime:

modalflow deploy --dags-source cloud-bucket \
  --dags-bucket s3://my-bucket/dags \
  --dags-bucket-secret my-aws-secret

By default, the Modal function image installs Airflow 3.1.5. To match your local Airflow version, use --airflow-version:

modalflow deploy --dags-source local --dags-path ./dags --airflow-version 3.1.8

To target a specific Modal environment, add --env <name> (default: main).

3. Configure Airflow

Set the executor class in airflow.cfg or via environment variable:

[core]
executor = modalflow.executor.ModalExecutor
export AIRFLOW__CORE__EXECUTOR=modalflow.executor.ModalExecutor

The executor reads MODALFLOW_ENV to find the right Modal app (default: main). Set it if you deployed with a custom --env.

Updating DAGs (volume mode)

With volume mode, use modalflow sync to push DAG changes without redeploying the function:

modalflow sync --dags-path ./dags --dags-volume my-dags

This does a full replace — files deleted locally are also removed from the volume.

Networking

Modal Functions run in Modal's cloud. To execute a task, the function must call back to your Airflow deployment's execution API. This means Airflow's API server must be reachable from the public internet.

The executor resolves the execution API URL in priority order:

  1. AIRFLOW__CORE__EXECUTION_API_SERVER_URL environment variable
  2. core.execution_api_server_url in airflow.cfg

The URL must end with /execution/ — the executor appends this automatically if missing. See apache/airflow#51235 for background.

Production

Set the URL to your Airflow API's public endpoint:

export AIRFLOW__CORE__EXECUTION_API_SERVER_URL=https://airflow.example.com/execution/

Common ways to expose the API:

  • Load balancer (ALB, NLB) in front of the Airflow API server
  • API Gateway with auth
  • Reverse tunnel (Cloudflare Tunnel, ngrok) if you can't expose a public endpoint directly

Local development

When running Airflow locally (e.g. airflow standalone), Modal functions need to reach your local execution API. Use a reverse tunnel (ngrok, Cloudflare Tunnel, etc.) and set the URL:

export AIRFLOW__CORE__EXECUTION_API_SERVER_URL=https://your-tunnel-url.ngrok-free.app/execution/

See .env.example for a full local development template.

Important: deploy with --airflow-version matching your local Airflow version to avoid API version mismatches between the SDK on Modal and your local Airflow server:

modalflow deploy --dags-source local --dags-path ./dags --airflow-version 3.1.8

Note: Only DAGs you deploy to Modal (via --dags-path) are available to task workers. Airflow's built-in example DAGs use a separate bundle (example_dags) that isn't present on Modal, so they will fail. Use your own DAGs.

Development

uv sync --extra dev
uv run modalflow deploy --help
uv run pytest                      # unit tests
make system.setup && make system.test.e2e   # E2E tests (requires Modal)

Metadata

Release files for modalflow 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for modalflow 0.3.1
File Size Uploaded Provenance
modalflow-0.3.1.tar.gz 10.9 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for modalflow 0.3.1
File Interpreter ABI Platform
modalflow-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 24.3 kB

Release files / modalflow-0.3.1.tar.gz

Download URL modalflow-0.3.1.tar.gz
Size 10.9 kB
Tags Source
SHA-256 checksum
How to use checksums
30565f02df416af0e6f0bf22d8d851460d1b4e3c7a47454a80e9e095ab26ce0e
BLAKE2b-256 checksum
How to use checksums
cb4fbac8dea0d4ca4f96ed1ce99ec40db3f2bc96448c3a5552bd0fe17a509dea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 20, 2026.

Transparency log

Release files / modalflow-0.3.1-py3-none-any.whl

Download URL modalflow-0.3.1-py3-none-any.whl
Size 13.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2036772b07b796f53ff4329fe3e5b6eb37f33907cd67cd5a4dc12f403575c535
BLAKE2b-256 checksum
How to use checksums
d19cc5b1cffed5afcec97c5c7fce69d87710aa5aa2911fbcae3dcb8961807117
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 20, 2026.

Transparency log

Security for modalflow 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for modalflow-0.3.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page