FastAPI Cloud
A hosting platform from the FastAPI team, and the second agent host in this workshop. It deploys straight from a GitHub repo with no config file at all — or with one command from your terminal, if you prefer.
This project has been deployed to it end to end. The steps below are the ones that actually worked.
Two ways to do it
Section titled “Two ways to do it”The whole thing happens in the browser. Nothing to install.
-
Push your repo to GitHub.
-
FastAPI Cloud dashboard → your team → create a new app from GitHub.
-
Connect your GitHub account, and install or update the FastAPI Cloud GitHub App when it asks.
-
Pick your GitHub account or organisation, then the repository.
-
Root Directory →
appThis is the one setting that matters for this repo.
pyproject.toml,uv.lockandmain.pyall live inapp/, not at the repo root — leave this blank and the build has no project to install. -
Create App.
It connects the repo and deploys the latest commit on your default branch. From then on, every push to that branch deploys automatically.
Already have an app and want to attach a repo to it? App → Settings → Source Repository → Connect, then the same account/repo picker.
Run all of this from app/ — that’s where the uv project (and the FastAPI
app it deploys) lives.
uv add --dev fastapi-cloud-cli
uv run fastapi login # opens a browseruv run fastapi deploy # detects the app, builds, deploysThat’s the whole thing. It detects your FastAPI app, packages it, and gives you a URL.
Because you run it from app/, there’s no root-directory setting to get
wrong — the CLI uploads the directory you’re standing in.
Both routes land in the same place, and you can mix them: create the app from the CLI and connect a repo later, or create it from GitHub and use the CLI for logs.
Environment variables
Section titled “Environment variables”Same principle as everywhere else: secrets in the platform, never the repo.
You need the same three as on Render — LLM_API_KEY, SUPABASE_URL,
SUPABASE_SECRET_KEY — plus ALLOWED_ORIGINS once you have a deployed client,
and TAVILY_API_KEY if you want web search.
- App details → Environment Variables in the sidebar
- Add Environment Variable
- Name and value
- Toggle Secret on for anything sensitive — the three above all qualify
- Save and Redeploy (or Save Only, which applies on the next deploy)
uv run fastapi env set LLM_API_KEYuv run fastapi env set SUPABASE_URLuv run fastapi env set SUPABASE_SECRET_KEYuv run fastapi env set TAVILY_API_KEY # optional — web searchWhy it works without a Dockerfile
Section titled “Why it works without a Dockerfile”Worth knowing, because it explains why there’s no config file in this repo for it:
- It prefers uv. If you have a
pyproject.tomland auv.lock, it installs from the lock file — the same “exact versions you tested” guaranteeuv sync --frozengives you on Render. Failing that it looks forpylock.toml, thenrequirements.txt. - It reads
.python-version.app/.python-versionis already there, so you get the interpreter this project was built against rather than whatever is newest. - It detects the app. If
fastapi devworks locally, it works there — no start command to write, no--host 0.0.0.0to remember.
That’s three of this project’s existing files doing deployment work for free.
It’s also why deploy/render.yaml is the only platform-specific file in the
repo.
App → Logs tab, updating in real time.
uv run fastapi logsHobby keeps 1 day of log and metric retention, which is enough to debug a deploy and not enough to investigate something from last week.
Free tier, as published
Section titled “Free tier, as published”| Hobby | |
|---|---|
| Price | $0 |
| Apps | 3 |
| Resources | 0.1 vCPU / 512 MB shared, bursting to 0.5 |
| Autoscale | up to 3 replicas |
| Scale-to-zero | yes, on by default |
| Custom domain | 1 |
| Log retention | 1 day |
| Credit card | not required |
Re-verify these before depending on them — beta pricing pages move.
Why Render is still the primary path
Section titled “Why Render is still the primary path”In its favour: a free Hobby plan with no credit card, GitHub deploys and a one-command CLI, automatic HTTPS, zero-downtime rollouts, scale-to-zero, secrets management, and a custom domain. For the framework this project is already built on, that’s a very short path from code to URL.
But:
- It’s a beta. Terms and limits can change. This workshop has to keep working for people following it months later.
- Hobby is 0.1 vCPU / 512 MB. Thin for a Python process that also hosts an MCP server, even with the burst headroom.
- Scale-to-zero and background tasks deserve a measurement. This entire project depends on work continuing after the HTTP response is sent, and scale-to-zero is on by default. We could not find published documentation on how Hobby’s scale-to-zero treats an in-flight background task once the request completes.
That third point is the one to actually check. On platforms where CPU is
allocated per request, a background task can be throttled the moment the
response goes out — which would break /runs specifically while leaving
/runs/naive looking fine. That’s the exact opposite of what this workshop
teaches.
Deploying to both
Section titled “Deploying to both”There’s real value in shipping the same app twice:
- It proves the architecture is the portable part. Nothing in
app/knows or cares which platform it’s on. - You get a fallback URL if one platform misbehaves during a demo.
- Comparing cold starts, logs, and deploy ergonomics between two platforms is deployment learning.
Nothing in this project is platform-specific. The only file that mentions Render
is deploy/render.yaml, and FastAPI Cloud needs no config file at all.
Remember to add both backend URLs wherever you’re switching between them —
the client’s Backend URL field takes either one, and each frontend origin
has to appear in ALLOWED_ORIGINS on both backends.
See also
Section titled “See also”- Render — the primary agent host
- Deploy the client — Vercel and GitHub Pages
- Naming GitHub deployments — optional; this repo deploys from GitHub Actions so its two hosts are told apart
- Troubleshooting