Modal
This guide will help you use setup an Inngest app in Modal, a platform for building and deploying serverless Python applications.
Setting up your development environment
This section will help you setup your development environment. You'll have an Inngest Dev Server running locally and a FastAPI app running in Modal.
Creating a tunnel
Since we need bidirectional communication between the Dev Server and your app, you'll also need a tunnel to allow your app to reach your locally-running Dev Server. We recommend using ngrok for this.
# Tunnel to the Dev Server's port
ngrok http 8288
This should output a public URL that can reach port 8288
on your machine. The URL can be found in the Forwarding
part of ngrok's output:
Forwarding https://23ef-173-10-53-121.ngrok-free.app -> http://localhost:8288
Creating and deploying a FastAPI app
Create an .env
file that contains the tunnel URL:
INNGEST_DEV=https://23ef-173-10-53-121.ngrok-free.app
Create a dependency file that Modal will use to install dependencies. For this guide, we'll use requirements.txt
:
fastapi==0.115.0
inngest==0.4.12
python-dotenv==1.0.1
Create a main.py
file that contains your FastAPI app:
import os
from dotenv import load_dotenv
from fastapi import FastAPI
import inngest
import inngest.fast_api
import modal
load_dotenv()
app = modal.App("test-fast-api")
# Load all environment variables that start with "INNGEST_"
env: dict[str, str] = {}
for k, v, in os.environ.items():
if k.startswith("INNGEST_"):
env[k] = v
image = (
modal.Image.debian_slim()
.pip_install_from_requirements("requirements.txt")
.env(env)
)
fast_api_app = FastAPI()
# Create an Inngest client
inngest_client = inngest.Inngest(app_id="fast_api_example")
# Create an Inngest function
@inngest_client.create_function(
fn_id="my-fn",
trigger=inngest.TriggerEvent(event="my-event"),
)
async def fn(ctx: inngest.Context, step: inngest.Step) -> str:
print(ctx.event)
return "done"
# Serve the Inngest endpoint (its path is /api/inngest)
inngest.fast_api.serve(fast_api_app, inngest_client, [fn])
@app.function(image=image)
@modal.asgi_app()
def fastapi_app():
return fast_api_app
Deploy your app to Modal:
modal deploy main.py
Your terminal should show the deployed app's URL:
└── 🔨 Created web function fastapi_app =>
https://test-fast-api-fastapi-app.modal.run
To test whether the deploy worked, send a request to the Inngest endpoint (note that we added the /api/inngest
to the Modal URL). It should output JSON similar to the following:
$ curl https://test-fast-api-fastapi-app.modal.run/api/inngest
{"schema_version": "2024-05-24", "authentication_succeeded": null, "function_count": 1, "has_event_key": false, "has_signing_key": false, "has_signing_key_fallback": false, "mode": "dev"}
Syncing with the Dev Server
Start the Dev Server, specifying the FastAPI app's Inngest endpoint:
npx inngest-cli@latest dev -u https://test-fast-api-fastapi-app.modal.run/api/inngest --no-discovery
In your browser, navigate to http://127.0.0.1:8288/apps
. Your app should be successfully synced.
Deploying to production
A production Inngest app is very similar to an development app. The only difference is with environment variables:
INNGEST_DEV
must not be set. Alternatively, you can set it to0
.INNGEST_EVENT_KEY
must be set. Its value can be found on the event keys page.INNGEST_SIGNING_KEY
must be set. Its value can be found on the signing key page.
Once your app is deployed with these environment variables, you can sync it on our new app page.
For more information about syncing, please see our docs.