1 · The agent
The FastAPI backend in app/. A running process that has to keep
working after the HTTP response is sent. This is what the workshop is
about. Deploy the agent →
Reference material for getting this — or your own project — onto the internet for free.
If you’re working through the tutorial, Build step 8 is the guided version. These pages are what you come back to afterwards.
This is the thing that trips people up. “Deploying the app” is actually two separate jobs, on two different kinds of host, with two completely different sets of constraints.
1 · The agent
The FastAPI backend in app/. A running process that has to keep
working after the HTTP response is sent. This is what the workshop is
about. Deploy the agent →
2 · The client
The Vite + React app in client/. A folder of static files. Any static
host will do, and none of them can break the architecture.
Deploy the client →
Both are free. Only the first one is hard, and the reason is worth saying out loud: a static host just serves bytes, so it cannot get the agent wrong. A backend host decides whether your code still gets CPU after it has replied — and that decision is the entire workshop.
Two free hosts, both verified end to end with this exact project. Deploy to one, then deploy to the other — shipping the same app twice is one of the cheapest ways to learn what’s your code’s fault and what’s the platform’s.
| Host | Free tier | Deploy by | Our take |
|---|---|---|---|
| Render | yes, no card | connecting a GitHub repo | Primary. Stable, known free-tier behaviour |
| FastAPI Cloud | yes, no card | GitHub in the dashboard, or fastapi deploy |
Second target. Lovely ergonomics; public beta |
| Render | FastAPI Cloud | |
|---|---|---|
| Free tier | yes, no card | Hobby, no card |
| Sleeps when idle | ~15 min | scale-to-zero |
| Cold start | ~1 minute | seconds |
| Deploy method | push to GitHub | push to GitHub, or one CLI command |
| Resources | small shared slice | 0.1 vCPU / 512 MB, bursts to 0.5 |
| Config in the repo | deploy/render.yaml |
none needed |
| Maturity | stable | public beta |
We recommend Render as the main path because its free-tier behaviour is well-documented and hasn’t moved. FastAPI Cloud is genuinely nice — it’s built by the FastAPI team, it deploys from GitHub with no config file at all, and it takes about two minutes — but read the caveats before you put anything you care about on a public beta.
Neither is the only option, and you shouldn’t pick a host from a table of free tiers anyway. Other hosts covers Hugging Face Spaces, Fly.io and the rest, and gives you the one question that actually decides whether a platform can run this architecture: does your code still get CPU after it has returned a response?
These apply to every backend host, and between them they cause most first-deploy failures.
1. Secrets live in the platform, never the repo.
.env locally, environment variables in the dashboard in production. The code
reads os.environ either way, so nothing changes between them. If a key ever
reaches git history, rotate it — deleting the file doesn’t help.
2. Bind to 0.0.0.0, not 127.0.0.1.
Inside a container, binding to localhost means nothing outside can reach you. It shows up as “port scan timeout” in the deploy log and wastes an afternoon.
3. Have a /health endpoint.
Two seconds to answer “is it alive, and can it reach the database?”. It’s also how you wake a sleeping free-tier service before a demo.
The client builds to a folder of static files, so this part is genuinely easy. The only thing that goes wrong is CORS, and it goes wrong every single time.
| Host | Free tier | Deploy by | Our take |
|---|---|---|---|
| Vercel | yes, no card | importing the repo in the dashboard | Bonus track. Two minutes, client/vercel.json is already written |
| GitHub Pages | yes | pushing to main |
Already wired up — the site build publishes the client at /demo/ |
Full walkthrough: Deploy the client →
Once both are live you have three origins in play — your backend, your client, and localhost — and they have to be told about each other:
client on Vercel ──fetch──▶ agent on Render VITE_API_URL ALLOWED_ORIGINS = the Render URL = the Vercel originTwo variables, pointing at each other. VITE_API_URL tells the client where the
API is; ALLOWED_ORIGINS tells the API which pages are allowed to call it. Get
one wrong and you get “Failed to fetch” with no useful error — see
Troubleshooting.
| Page | For |
|---|---|
| Render | The primary agent host. Free web services, deploys from GitHub. |
| FastAPI Cloud | The second agent host. GitHub or one command — read the caveats first. |
| Deploy the client | Vercel and GitHub Pages, plus making CORS work. |
| Other hosts | Hugging Face Spaces, Fly.io — and how to judge any host. |
| Naming GitHub deployments | Optional. Telling two providers apart in the Deployments tab. |
| Troubleshooting | When it doesn’t work, and keeping it alive. |
Free tier isn’t a smaller paid tier. It’s a different set of trade-offs: your server sleeps, your database pauses, your model rate-limits, and your disk forgets. You’re trading money for latency and reliability.
That’s a fine trade for a demo. Know that you’re making it.