Deploy a Python FastAPI Backend on Vercel Serverless Functions
Ship a FastAPI app to Vercel with zero-config framework detection and a minimal vercel.json.
What you'll build
A FastAPI backend deployed to Vercel as a serverless function — you'll get a live HTTPS URL with auto-generated Swagger docs, scale-to-zero pricing, and no servers to patch.
Prerequisites
- Python 3.12, 3.13, or 3.14 locally. Vercel's Python runtime defaults to 3.12; this tutorial pins it explicitly.
- Node.js 20+ to run the Vercel CLI. Verified against CLI 58.4.0 (Vercel's FastAPI support requires at least 48.1.8):
npm i -g vercel - A free Vercel Hobby account.
- Verified against FastAPI 0.141.1 and the Vercel Python runtime docs (last updated July 2026). Commands are macOS/Linux; on Windows, activate the venv with
.venv\Scripts\activateinstead.
One thing before you start: older tutorials tell you to put your app in api/index.py and wire up rewrites in vercel.json. That pattern is obsolete. Vercel now detects FastAPI automatically from your dependencies and serves the whole app as a single function — vercel.json is only for overrides.
1. Scaffold the project
mkdir fastapi-vercel && cd fastapi-vercel
python3 -m venv .venv
source .venv/bin/activate
printf 'fastapi==0.141.1\n' > requirements.txt
pip install -r requirements.txt
requirements.txt matters beyond local installs: Vercel reads it to detect the FastAPI framework preset and to install dependencies at build time. Keep it to runtime packages only — Python bundles aren't tree-shaken, and the standard limit is 500 MB uncompressed.
2. Write the app
Vercel looks for a FastAPI instance named app in app.py, index.py, server.py, main.py, wsgi.py, or asgi.py (at the root, or inside src/, app/, or api/). Create main.py at the project root:
from fastapi import FastAPI
app = FastAPI(title="Notes API")
NOTES = {1: "Ship it", 2: "Then iterate"}
@app.get("/")
def home():
return {"status": "ok", "service": "notes-api"}
@app.get("/api/notes/{note_id}")
def read_note(note_id: int):
return {"note_id": note_id, "text": NOTES.get(note_id, "not found")}
The variable must be named app — that's the contract with the runtime. If your app lives in a nonstandard module, point Vercel at it with tool.vercel.entrypoint = "my_package.api:app" in pyproject.toml.
3. Pin the runtime and configure vercel.json
Pin the Python version so builds don't shift under you when Vercel changes its default:
printf '3.12\n' > .python-version
Then create vercel.json. The functions entry is keyed by your entrypoint file; maxDuration raises the execution ceiling to 60 seconds, and excludeFiles keeps tests out of the bundle:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"functions": {
"main.py": {
"maxDuration": 60,
"excludeFiles": "{tests/**,**/test_*.py}"
}
}
}
No builds, no routes, no rewrites — FastAPI handles its own routing, and Vercel forwards every request to it.
4. Run it locally
vercel login
vercel dev
The first run walks you through linking the directory to a new Vercel project — accept the defaults. vercel dev serves the app at http://localhost:3000, emulating the production runtime (which is why it's worth using over plain uvicorn before you ship).
5. Deploy
vercel --prod
That's the whole deploy. The CLI builds remotely and prints a Production: URL when it's live. For real projects, push the repo to GitHub and import it in the Vercel dashboard instead — every push then deploys automatically, with preview URLs per branch.
Verify it works
Hit your production URL (substitute your own):
curl https://fastapi-vercel-yourname.vercel.app/api/notes/1
Expected output:
{"note_id":1,"text":"Ship it"}
Then open https://<your-url>/docs in a browser — you should see FastAPI's interactive Swagger UI listing both endpoints. If both respond, your app is live as a Vercel Function on Fluid compute, scaling with traffic automatically.
Troubleshooting
404: NOT_FOUND on every route after deploy. Vercel never found your entrypoint, so nothing is serving. Confirm the file is one of the supported names, sits in a supported location, and the variable is literally app — or set tool.vercel.entrypoint in pyproject.toml.
Build fails with ModuleNotFoundError: No module named 'fastapi'. Your requirements.txt (or pyproject.toml) isn't at the project root, or doesn't list fastapi. Vercel only installs what's declared there — your local venv is irrelevant at build time.
504: GATEWAY_TIMEOUT with code FUNCTION_INVOCATION_TIMEOUT. The request exceeded your plan's execution limit. Raise maxDuration in vercel.json (step 3), and check for slow upstream calls or handlers that never return a response.
Deploy fails on bundle size. Everything reachable at build time gets bundled — there's no tree-shaking. Trim requirements.txt to runtime-only packages and extend excludeFiles; Large Functions (public beta) raises the cap to 5 GB on Fluid compute if you genuinely need it.
Next steps
Add environment variables with vercel env add and pull them locally with vercel env pull. Use FastAPI lifespan events for startup logic like database pools — but keep shutdown cleanup under 500 ms, Vercel's hard SIGTERM limit. Serve static files from a public/ directory (CDN-backed, no app.mount needed), and when a single function stops being enough, look at Vercel's cron jobs and Workflows for background work.
Sources & further reading
- Deploy a FastAPI app on Vercel — vercel.com
- Using the Python Runtime with Vercel Functions — vercel.com
- How to ship a FastAPI app on Vercel — vercel.com
- FUNCTION_INVOCATION_TIMEOUT Error — vercel.com
- fastapi 0.141.1 — pypi.org
Ji-ho covers the increasingly tangled overlap between cloud architecture and security, drawing on a background as a penetration tester to keep his reporting grounded in real-world attack paths. He never lets a vendor claim go unquestioned and insists that every buzzword come with a proof of concept.
Discussion 0
No comments yet
Be the first to weigh in.