| title | FastAPI | ||||
|---|---|---|---|---|---|
| description | A FastAPI server | ||||
| tags |
|
A production-ready FastAPI template with PostgreSQL, fully async, and modern Python tooling.
CHANGELOG — See what's changed between versions.
- FastAPI 0.139+ — JSON serialized natively by pydantic-core (Rust)
- Fully async — endpoints, CRUD, and database layer
- SQLAlchemy 2.0 with async engine and
select()style queries - UUIDv7 primary keys — time-ordered for B-tree locality (native in PostgreSQL 18)
- Alembic async migrations included
- Pydantic v2 for request/response validation and settings management
- Pure ASGI middleware for doc protection (no
BaseHTTPMiddlewareoverhead) - Typed lifespan state with proper startup/shutdown lifecycle
- uvloop + httptools for maximum ASGI performance
- GZIP compression for responses > 1KB
- Session-based auth protecting
/docsand/redoc /healthendpoint for platform healthchecks- uv for fast, reproducible dependency management
- Locust load testing included
- Memory-tuned Docker image — multi-stage build, ~62MB idle (Railway bills by memory)
├── src/
│ ├── backend/
│ │ ├── main.py # FastAPI app entry point
│ │ ├── api/v1/endpoints/ # Route handlers
│ │ ├── core/ # Config, lifespan, middleware, routers
│ │ ├── crud/ # Service layer (async CRUD)
│ │ ├── dependencies/ # Database setup, DI
│ │ ├── models/ # SQLAlchemy ORM models
│ │ ├── schemas/ # Pydantic schemas
│ │ ├── security/ # Authentication
│ │ └── data/ # Seed data
│ └── frontend/
│ └── login/ # Login page templates & static files
├── migrations/ # Alembic async migrations
├── tests/ # Async test suite
├── alembic.ini # Alembic config (URL comes from app settings)
├── pyproject.toml # Dependencies & project config
├── Dockerfile # Multi-stage build with uv
├── locustfile.py # Load testing
└── .env.example # Environment variable template
- Python 3.12+
- uv package manager
# Clone the repository
git clone https://github.com/yuting1214/Fullstack-FastAPI.git
cd Fullstack-FastAPI
# Install dependencies
uv sync
# Copy environment template
cp .env.example .env
# Edit .env with your values
# Run in development mode (SQLite, auto-reload)
uv run python -m src.backend.main
# Run in production mode (PostgreSQL)
ENV_MODE=prod HOST=0.0.0.0 uv run python -m src.backend.mainTables are auto-created on startup, so the one-click deploy needs no manual step.
For controlled schema evolution, use Alembic (the URL is resolved from the same
ENV_MODE / DATABASE_URL settings the app uses):
uv run alembic upgrade head # apply migrations
uv run alembic revision --autogenerate -m "change" # generate a new migrationuv sync --extra dev
uv run pytestNote: Tests use
httpx.AsyncClientviaASGITransport, which does not trigger FastAPI's lifespan events. The sharedtests/conftest.pyhandles DB table creation and teardown automatically. If you add new tests, thesetup_dbfixture runs viaautouse— no manual setup needed.
uv run locust
# Open http://localhost:8089docker build -t fullstack-fastapi .
docker run -p 5000:5000 fullstack-fastapi| Method | Path | Description |
|---|---|---|
GET |
/ |
Onboarding message |
GET |
/health |
Liveness probe (healthchecks) |
GET |
/login |
Login page |
POST |
/login |
Authenticate |
GET |
/logout |
Clear session |
POST |
/api/v1/messages/ |
Create message |
GET |
/api/v1/messages/ |
List messages |
GET |
/api/v1/messages/{id} |
Get message |
PUT |
/api/v1/messages/{id} |
Update message |
DELETE |
/api/v1/messages/{id} |
Delete message |
See .env.example for all available configuration options.
Runtime behavior is controlled by env vars (no CLI flags), so the app also runs
under plain uvicorn src.backend.main:app:
| Variable | Default | Purpose |
|---|---|---|
ENV_MODE |
dev |
dev = SQLite + auto-reload, prod = PostgreSQL |
HOST |
127.0.0.1 |
Bind address (0.0.0.0 in the Docker image) |
PORT |
5000 |
Listen port (set automatically by Railway) |
DATABASE_URL |
— | PostgreSQL URL in prod (injected by Railway) |
USER_NAME / PASSWORD |
auto-generated | API docs login — prompted during Railway onboarding; if left empty, generated and printed once in the startup logs |
SECRET_KEY |
auto-generated | Session signing key — set a stable value to keep sessions across restarts |
Railway bills by memory per minute, so the image is tuned for a low idle footprint — ~62MB idle (measured via cgroup in Docker), down from ~150MB:
- The container execs the venv Python directly — no resident
uv runwrapper process MALLOC_ARENA_MAX=2+MALLOC_TRIM_THRESHOLD_cap glibc arena bloat- Bytecode is precompiled at build time (
UV_COMPILE_BYTECODE=1) for faster, leaner cold starts - Multi-stage build ships only the venv and
src/— no build tools in the final image
Tip: if your traffic is bursty, enable Railway's App Sleeping on the service — compute cost drops to ~$0 while idle, and this template's single-process design is compatible with it.