Migrating from FastAPI
JustAPI is engineered as a drop-in replacement for FastAPI. In most cases, migration is as simple as changing imports.
Quick Migration
Section titled “Quick Migration”1. Change Imports
Section titled “1. Change Imports”# FastAPIfrom fastapi import FastAPI, Depends, HTTPException, Query, Path, Headerfrom fastapi.responses import JSONResponse
# JustAPI — same names, same APIfrom justapi import JustAPIApp, Depends, HTTPException, Query, Path, Headerfrom justapi.responses import JSONResponse2. Replace the App Constructor
Section titled “2. Replace the App Constructor”# FastAPIapp = FastAPI(title="My API", version="1.0.0")
# JustAPIapp = JustAPIApp(title="My API", version="1.0.0")3. Update the Run Command
Section titled “3. Update the Run Command”# FastAPI (requires uvicorn)# uvicorn main:app --host 0.0.0.0 --port 8000
# JustAPI — built-in Rust serverif __name__ == "__main__": app.run("0.0.0.0:8000")4. (Optional) Update Requirements
Section titled “4. (Optional) Update Requirements”# FastAPI requirementsfastapi==0.109.0uvicorn[standard]==0.27.0
# JustAPI requirements — one dependencyjustapi>=2.0.0Import Mapping
Section titled “Import Mapping”| FastAPI Import | JustAPI Import | Notes |
|---|---|---|
FastAPI |
JustAPIApp |
Core application class |
APIRouter |
APIRouter |
Same API, works identically |
Depends |
Depends |
Dependency injection |
HTTPException |
HTTPException |
Error raising |
Query |
Query |
Query parameter extraction |
Path |
Path |
Path parameter extraction |
Header |
Header |
Header extraction |
Cookie |
Cookie |
Cookie extraction |
Body |
Body |
Body parameter extraction |
File |
File |
File upload |
Form |
Form |
Form field extraction |
UploadFile |
UploadFile |
Uploaded file representation |
Response |
Response |
Base response class |
JSONResponse |
JSONResponse |
JSON response |
HTMLResponse |
HTMLResponse |
HTML response |
PlainTextResponse |
PlainTextResponse |
Plain text response |
RedirectResponse |
RedirectResponse |
HTTP redirect |
StreamingResponse |
StreamingResponse |
Streaming response |
RequestValidationError |
RequestValidationError |
Validation error |
Side-by-Side: Complete App
Section titled “Side-by-Side: Complete App”FastAPI
Section titled “FastAPI”from fastapi import FastAPI, Depends, HTTPExceptionfrom pydantic import BaseModel
app = FastAPI(title="Pet Store")
class Pet(BaseModel): name: str species: str
def verify_token(token: str = Header(...)): if token != "secret": raise HTTPException(401)
@app.get("/pets/{pet_id}")def get_pet(pet_id: int, token: str = Depends(verify_token)): return {"pet_id": pet_id}
@app.post("/pets/")def create_pet(pet: Pet): return {"name": pet.name}JustAPI (Same Logic)
Section titled “JustAPI (Same Logic)”from justapi import JustAPIApp, Depends, HTTPException, Headerfrom pydantic import BaseModel
app = JustAPIApp(title="Pet Store")
class Pet(BaseModel): name: str species: str
def verify_token(token: str = Header(...)): if token != "secret": raise HTTPException(401)
@app.get("/pets/{pet_id}")def get_pet(pet_id: int, token: str = Depends(verify_token)): return {"pet_id": pet_id}
@app.post("/pets/")def create_pet(pet: Pet): return {"name": pet.name}Middleware Migration
Section titled “Middleware Migration”# FastAPI@app.middleware("http")async def add_header(request, call_next): response = await call_next(request) response.headers["X-Custom"] = "value" return response
# JustAPI — identical syntax@app.middleware("http")def add_header(request, call_next): response = call_next(request) response["headers"] = response.get("headers", []) + [(b"X-Custom", b"value")] return responseWhat Changes
Section titled “What Changes”- Running the server: JustAPI’s
app.run()replaces uvicorn/gunicorn - Middleware signature: Slightly different header manipulation (tuple-based)
- OpenAPI docs: Same URLs (
/docs,/redoc), plus Scalar UI at/scalar
What Stays the Same
Section titled “What Stays the Same”- Route decorators (
@app.get,@app.post, etc.) - Pydantic model validation
- Dependency injection (
Depends) - Exception handling (
HTTPException, custom handlers) - Path/Query/Header/Cookie/Body extractors
- Sub-routers (
APIRouter,include_router) - WebSocket handlers
- Static file serving
What You Gain
Section titled “What You Gain”| Metric | FastAPI + Uvicorn | JustAPI | Improvement |
|---|---|---|---|
| Throughput | 36,189 req/s | 701,234 req/s | ~20x faster |
| p99 Latency | 24.63 ms | 0.19 ms | ~130x lower |
| JSON validation | Python runtime | Rust (GIL-free) | Zero overhead |
| DB queries | Python asyncio | Rust sqlx pool | Native speed |
| Memory usage | Per-request overhead | Zero-copy buffers | Minimal |
Migration Checklist
Section titled “Migration Checklist”- Replace
from fastapi importwithfrom justapi import - Replace
FastAPI()withJustAPIApp() - Replace
uvicorn.run()withapp.run() - Update middleware response header manipulation
- Test all routes return the same responses
- Compare performance with your load testing tool
- Update requirements.txt / pyproject.toml
- Update Dockerfile if using custom build
Rollback Plan
Section titled “Rollback Plan”JustAPI is designed for gradual adoption. You can:
- Migrate one route at a time using
APIRouter - Run JustAPI and FastAPI side-by-side behind a reverse proxy
- Keep your existing tests — the response format is identical
Next Steps
Section titled “Next Steps”- First Steps — Run your migrated app
- API Reference — Explore JustAPI-specific features
- Performance Tuning — Optimize your migrated app