Skip to main content

Serverless Airflow Executor on Modal

Project description

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)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

modalflow-0.3.1.tar.gz (10.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

modalflow-0.3.1-py3-none-any.whl (13.4 kB view details)

Uploaded Python 3

File details

Details for the file modalflow-0.3.1.tar.gz.

File metadata

  • Download URL: modalflow-0.3.1.tar.gz
  • Upload date:
  • Size: 10.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for modalflow-0.3.1.tar.gz
Algorithm Hash digest
SHA256 30565f02df416af0e6f0bf22d8d851460d1b4e3c7a47454a80e9e095ab26ce0e
MD5 7930fac7d902af72f6ba3e70b986e475
BLAKE2b-256 cb4fbac8dea0d4ca4f96ed1ce99ec40db3f2bc96448c3a5552bd0fe17a509dea

See more details on using hashes here.

Provenance

The following attestation bundles were made for modalflow-0.3.1.tar.gz:

Publisher: publish.yml on agupta01/modalflow

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file modalflow-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: modalflow-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 13.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for modalflow-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2036772b07b796f53ff4329fe3e5b6eb37f33907cd67cd5a4dc12f403575c535
MD5 d1584ed30b848b44c4ee7ea2b7b6a16a
BLAKE2b-256 d19cc5b1cffed5afcec97c5c7fce69d87710aa5aa2911fbcae3dcb8961807117

See more details on using hashes here.

Provenance

The following attestation bundles were made for modalflow-0.3.1-py3-none-any.whl:

Publisher: publish.yml on agupta01/modalflow

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page