Deploy a FastAPI service (Python)
Deploy async FastAPI services with a pip build, Uvicorn serving the ASGI app, a managed PostgreSQL database and HTTPS. The interactive /docs page is live as soon as the release passes its health check.
Prerequisites
- Python 3.11 or newer locally, and a
requirements.txt(orpyproject.toml) listingfastapianduvicorn. - The app object importable from the project root, for example
app = FastAPI()inmain.py.
How Deployxa detects FastAPI
A requirements.txt, Pipfile or pyproject.toml marks a Python project. Choose the FastAPI preset (or keep Auto-detect) and set the start command explicitly; the generic Python default, python app.py, does not start an ASGI server.
Required config: host 0.0.0.0 and the port
Uvicorn binds to 127.0.0.1 by default, which the health check cannot reach. Always pass --host 0.0.0.0, and a port that matches the service's Internal Port. To follow a PORT variable instead of a fixed number, run it through a shell:
# fixed port (matches the preset)
uvicorn main:app --host 0.0.0.0 --port 8000
# follow $PORT, default 8000, with 2 worker processes
sh -c 'uvicorn main:app --host 0.0.0.0 --port ${PORT:-8000} --workers 2 --proxy-headers --forwarded-allow-ips="*"'--proxy-headers with --forwarded-allow-ips makes request.url use https behind the proxy, so redirects and generated links are correct.
# main.py
import os
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(title="My API")
app.add_middleware(
CORSMiddleware,
allow_origins=[o for o in os.getenv("CORS_ORIGINS", "").split(",") if o],
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health")
def health():
return {"ok": True}Environment variables
Databases and migrations
In the wizard's Configure step, set Database to PostgreSQL. The connection string is injected into the app as DATABASE_URL, so nothing needs to be committed. Choose SQLite only for small apps: it lives on a persistent volume and has no server.
For async SQLAlchemy, swap the scheme to the asyncpg driver in code, so the injected value can stay as it is:
# db.py
import os
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
url = os.environ["DATABASE_URL"].replace("postgres://", "postgresql://", 1)
url = url.replace("postgresql://", "postgresql+asyncpg://", 1)
engine = create_async_engine(url, pool_size=5, pool_pre_ping=True)
SessionLocal = async_sessionmaker(engine, expire_on_commit=False)Run Alembic before the server so the schema is current when traffic switches: sh -c 'alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 8000'.
Deploy
From the dashboard
- 1Source
Open
Dashboard → Projects → New project(/dashboard/projects/new). Pick the GitHub repository and branch, or upload a.ziparchive of the project. - 2Configure
Leave the framework preset on Auto-detect or choose FastAPI. Check the fields under advanced settings:
- Build command:
pip install -r requirements.txt - Root directory:
./, or the sub-folder that holds the app in a monorepo - Database: PostgreSQL
- Build command:
- 3Environment
Add your variables in the table, or paste a whole
.envfile into the Bulk / .env tab. - 4Deploy
Start the deploy and watch the build log. When the release passes its health check it is served over HTTPS on its Deployxa URL.
- 5Confirm the start command and port
Open the project's Environment Canvas tab and select the web service. Set Start Command to
uvicorn main:app --host 0.0.0.0 --port 8000. Set Internal Port to8000so it matches the port your app listens on. Save and redeploy if you changed anything.
From the CLI
$ npm install -g @deployxa/cli $ deployxa login $ cd my-app $ deployxa link # pick an existing project, or skip: deploy creates one $ deployxa env set CORS_ORIGINS "https://app.example.com" $ deployxa deploy $ deployxa logs --live # stream build and runtime logs $ deployxa open # open the live URL
If the folder is not linked, deployxa deploy creates a project named after the folder and links it (the link is saved in .deployxa/config.json). Later runs deploy the linked project. deployxa status shows the latest deployment and deployxa rollback previous returns to the release before it.
deployxa deploy packages the folder exactly as it is on disk; it does not read .gitignore. Delete local node_modules, virtualenvs, build output and real .env files first, or deploy from a clean clone. Set secrets with deployxa env set instead of shipping them in the archive.deployxa create fastapi scaffolds a minimal FastAPI starter if you want to try the flow first.
Custom domain
Go to Dashboard → Domains, choose Connect a domain you already own and pick this project. Deployxa then shows the DNS records to create at your DNS provider:
DNS changes can take several minutes to propagate; use Retry verification once they have. A Let's Encrypt certificate is issued after the domain verifies. From a linked folder you can do the same with the CLI:
$ deployxa domains add app.example.com $ deployxa dns # Waiting → Verified → SSL Active $ deployxa domains list
Common errors and fixes
Start with deployxa logs --live (or the deployment's log view in the dashboard): the build log shows dependency and compile failures, the runtime log shows crashes and bind errors. See also Troubleshooting.