You’ll build a full serverless infrastructure framework for scheduling and provisioning workflows.
GitHub will act as the source of truth, Prefect will be the orchestrator, and Modal will be the serverless infrastructure.
You’ll only pay for the Modal CPU time you use.
First, here’s a recap of some important terms:
| Term | Definition |
|---|---|
| Flow | A Python function in a file, decorated with @flow, that is an entrypoint to perform a task in Prefect. |
| Run | An instance of a flow, executed at a specific time with a specific payload. |
| Deployment | A manifest around a flow, including where it should run, when it should run, and any variables it needs to run. A deployment can schedule your flows, creating runs when needed. |
| Work Pool | An interface to the hardware used to run a given flow. |
Prerequisites
- A free Prefect Cloud account.
- A free Modal account.
Create a GitHub repository
Create a GitHub repository containing your Prefect flows. You can reference the Ben-Epstein/prefect-modal repository for a complete example. Your repository should have aprefect.yaml deployment configuration file, standard Python tooling, and CI/CD.
-
Start by creating the following
Makefileto keep things easy:Makefile -
Set up and manage your environment with
uv. -
Create your Python project.
If
uvcreates apython-versionthat is pinned to a micro version (for example, 3.12.6), remove the micro version (for example, 3.12) to avoid downstream issues. -
Add your dependencies:
-
Add the following to the end of the
pyproject.tomlfile created byuv: -
Initialize the Prefect environment:
You will be prompted to choose your code storage; select
gitto store code within a git repository.
-
Because this is meant to be a scalable repository, create a submodule just for your workflows.
prefect.yaml file that you generated.
prefect.yaml
pull, which defines the repository and branch to pull from, as well as deployments, which define the flows that will be run at some schedule on a work_pool.
The work pool will be set to modal later in this tutorial.
Finally, create your flow.
src/prefect_modal/flows/flow1.py
Give Prefect access to your GitHub repository
First, authenticate to Prefect Cloud.
Give the token a name, an expiration date, and repository access.
Once you’ve created the token, copy it and give it to Prefect.
First, run:
prefect-modal.
In prefect.yaml, edit the pull: section as follows:
- Replace the
access_tokenkey name withcredentials. - Change the repository name to the name of your repository.
Typically,
uv sync creates a new virtual environment.
The following steps show how to tell uv to use the root Python version.main.
This means that if you push new code to main, the next run of a flow in Modal will change to whatever is in main.
To keep this stable, you can set that to a release branch, for example, to only update that release branch when you’re stable and ready.
Now, configure a few more options on the deployment to get it ready: entrypoint, schedule, and description.
Because you referenced the entrypoint as a module and not a path, you can call it from anywhere (as long as it’s installed).
This is much more flexible.
Connect Prefect and Modal
You need to give Prefect access to your Modal account to provision a serverless instance to run your flows and tasks. Modal will be the Work Pool in Prefect terms, remaining off when unused, and spinning up the infrastructure you need when a new flow run is scheduled. Prefect makes this incredibly easy. First, authenticate with Modal:pref-modal-pool in the last command is custom, you can name it whatever you want.
Take the work pool name and update your prefect.yaml file with it.
prefect.yaml
This
UV_PROJECT_ENVIRONMENT is how you tell uv to use the root python.
You could pip install without uv but it would be significantly slower (minutes instead of seconds) and you can’t leverage your lockfile, resulting in unexpected behavior!git add . && git commit -m "prefect modal" && git push to get your code into GitHub, and then uv run prefect deploy --all to get your deployment live.
But first, learn how to automate Prefect deployments.
Configure CI/CD
Since the code must exist in GitHub in order for Modal to download, install, and run it, GitHub should also be the source of truth for telling Prefect what to do with the code. First, create two secrets to add to the GitHub repository:PREFECT_API_KEY and PREFECT_API_URL.
-
For
PREFECT_API_URL, the format is as follows:https://api.prefect.cloud/api/accounts/{account_id}/workspaces/{workspace_id}. Go to the Prefect Cloud Dashboard, and then extract the account ID and workspace ID from the URL.The Prefect console URL uses/accountand/workspacebut the API uses/accountsand/workspaces, respectively. -
For
PREFECT_API_KEY, go to the API keys page and create a new API key.
Click New repository secret to add these secrets to your GitHub repository.
Now, add a simple GitHub workflow.
Create a new folder in the root of your GitHub repository:
.github/workflows/prefect_cd.yaml
make prefect-deploy command is used to deploy the flows in your deployment.
You can run
make prefect-deploy locally at any time to keep your deployment up to date.Makefile.
Makefile
make prefect-deploy once to make sure everything works.
Prefect will suggest changes to prefect.yaml, which you should accept.
You let Prefect override your deployment spec, which allowed your CD to run without any interruptions or prompts.
If you go to the Deployment page in Prefect Cloud, you’ll see your deployment!
There are no runs yet.
The output from make prefect-deploy shows the command to run your deployed flow.
However, since the code isn’t in GitHub yet, this will fail.
To fix this, push your code:
You can see the flow run in Prefect Cloud as well.
The flow will run automatically at 12 PM, but you can also run it manually.
In a new browser tab, open your [https://modal.com/apps/](Modal dashboard) alongside your Prefect Cloud dashboard.
In your terminal, run the following command:
Click into the app and then click App Logs on the left to show everything that’s happening inside the flow run!
Click on a specific log line to get more details.
If you open the URL in that log, you’ll see the corresponding logs in Prefect Cloud.
As you make changes to either the code or deployment file, Prefect will redeploy and Modal will automatically pick up changes.
You’ve successfully built your first Prefect deployment that runs on Modal every hour!
For more information about CI/CD in Prefect, see Build deployments via CI/CD.