Skip to content

Repository files navigation

FastrAPI (Fast + Rust + API)

PyPI Downloads

FastRAPI GIF

FastrAPI is a high-performance web framework that supercharges your Python APIs with the power of Rust. Built on Axum and PyO3, it delivers unmatched speed, type safety, and developer-friendly Python syntax. Create robust, async-ready APIs with minimal overhead and maximum throughput. FastrAPI is your drop-in replacement for FastAPI, offering familiar syntax with up to 6x faster performance.

Key Features

  • High Speed: Powered by Rust and Axum, FastrAPI delivers up to 6x faster performance than FastAPI, making your APIs scream.
  • Python First: Write same Python code, 0 Rust knowledge needed. FastrAPI handles the heavy lifting behind the scenes.
  • Pydantic Powered: Seamless integration with Pydantic for effortless request and response validation, keeping your data in check.
  • Async Native: Built on Tokio's async runtime, FastrAPI maximizes concurrency for handling thousands of requests with ease.
  • Ultra Lightweight: Minimal runtime overhead with maximum throughput.
  • Drop in Replacement: Drop in compatibility with the same FastAPI's beloved decorator syntax, so you can switch without rewriting your codebase.
  • Middleware Support: tower-http support for CORS, GZip, Session, and TrustedHost middleware.

Is it as fast as claimed?

Yes. Powered by Rust and Axum, FastrAPI outperforms FastAPI by up to 6x in real-world benchmarks, with no compromises on usability. Check it out here

FastRAPI vs other frameworks comparision

Do I need to know Rust?

Nope. FastrAPI lets you write 100% Python code while still leveraging Rust's performance under the hood.

Can it handle complex APIs?

Absolutely, FastrAPI scales effortlessly for small projects and massive enterprise grade APIs alike.

Will it keep up with FastAPI updates?

Yes. FastrAPI mirrors FastAPI's syntax, ensuring compatibility and instant access to workflows.

Installation

uv

uv install fastrapi

pip

pip install fastrapi

Build from Source

maturin build --release --pgo --generate-stubs

Switch from FastAPI

- from fastapi import FastAPI
+ from fastrapi import FastrAPI

Get Started

from fastrapi import FastrAPI
app = FastrAPI()

@app.get("/hello")
def hello():
    return {"Hello": "World"}

@app.get("/healthz", cache_resp=True)
def healthz():
    return {"ok": True}

@app.post("/echo")
def echo(data):
    return {"received": data}

if __name__ == "__main__":
    app.serve("127.0.0.1", 8000)

Now, test it with:

curl http://127.0.0.1:8000/hello

For the POST endpoint:

curl --location 'http://127.0.0.1:8000/echo' \
--header 'Content-Type: application/json' \
--data '{"foo": 123, "bar": [1, 2, 3]}'
Show Pydantic example
from pydantic import BaseModel
from fastrapi import FastrAPI

api = FastrAPI()

class User(BaseModel):
    name: str
    age: int

@api.post("/create_user")
def create_user(data: User):
    return {"msg": f"Hello {data.name}, age {data.age}"}

api.serve("127.0.0.1", 8000)
Show ResponseTypes Example
from fastrapi import FastrAPI
from fastrapi.responses import HTMLResponse, JSONResponse

api = FastrAPI()

@api.get("/html")
def get_html() -> HTMLResponse:
    return HTMLResponse("<h1>Hello</h1>")

api.serve("127.0.0.1", 8000)
Show Middleware Example
from fastrapi import FastrAPI
from fastrapi.responses import JSONResponse

from fastrapi.middleware import (
    CORSMiddleware,
    TrustedHostMiddleware,
    GZipMiddleware,
    SessionMiddleware
)

app = FastrAPI()

# TrustedHost Middleware
app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=["127.0.0.1", "localhost", "127.0.0.1:8000"],
    www_redirect=True
)

# CORS Middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["GET", "POST"],
    allow_headers=["*"],
    allow_credentials=False
)

# 3. GZip Middleware
app.add_middleware(
    GZipMiddleware,
    minimum_size=500,
    compresslevel=9
)

# 4. Session Middleware
app.add_middleware(
    SessionMiddleware,
    secret_key="super-duper-secret-key-change-this-in-prod-pwease-uwu-BUT-MAKE-IT-LONGER-NOW",
    session_cookie="fastrapi_session",
    max_age=3600,
    https_only=False
)

# ROUTES
@app.get("/")
def index() -> JSONResponse:
    return JSONResponse({"status": "running"})

@app.get("/heavy")
def heavy_data() -> JSONResponse:
    # response large enough to trigger GZip compression
    large_data = "x" * 1000
    return JSONResponse({
        "data": large_data,
        "note": "Check content-encoding header!"
    })

# Session Test: Increment a counter stored in the cookie
@app.get("/counter")
def session_counter(request) -> JSONResponse:
    # For now, this verifies the Middleware sets the cookie correctly.
    return JSONResponse({"message": "Session cookie should be set"})

if __name__ == "__main__":
    app.serve("127.0.0.1", 8000)

# Test with:
# curl -v -H "Host: 127.0.0.1" http://127.0.0.1:8000/
# curl -v -H "Origin: http://example.com" http://127.0.0.1:8000/
Show Lifespan Example
from contextlib import asynccontextmanager
from fastrapi import FastrAPI

shared = {}

@asynccontextmanager
async def lifespan(app: FastrAPI):
    shared["ready"] = True
    app.title = "FastrAPI && lifespan"
    try:
        yield
    finally:
        shared.clear()

app = FastrAPI(lifespan=lifespan)

@app.get("/health")
def health():
    return {"ready": shared.get("ready", False), "title": app.title}

app.serve("127.0.0.1", 8080)

If you provide lifespan=..., on_startup and on_shutdown handlers are not called.

Show Startup / Shutdown Example
from fastrapi import FastrAPI

events = []

def startup():
    events.append("startup")

async def shutdown():
    events.append("shutdown")

app = FastrAPI(
    on_startup=[startup],
    on_shutdown=[shutdown],
)

@app.get("/events")
def get_events():
    return {"events": events}

app.serve("127.0.0.1", 8080)

Startup-Precomputed Routes

Use cache_resp=True only for immutable responses. FastrAPI calls the handler during startup, stores the rendered response bytes and headers, and serves that route through a no-Python Axum path.

@app.get("/", cache_resp=True)
def hello():
    return {"Hello": "World"}

Performance

Benchmarks using k6 show it outperforms FastAPI + Guvicorn across multiple worker configurations.

Benchmarking Locally

For real benchmark numbers, build the PyO3 extension in release mode first:

maturin develop --release
python examples/basic.py
k6 run benchmarks/stress.js

If you benchmark a debug build, Rust-side overhead will be much higher and the numbers will be misleading.

🖥️ Test Environment

  • Kernel: 6.16.8-arch3-1
  • CPU: AMD Ryzen 7 7735HS (16 cores, 4.83 GHz)
  • Memory: 15 GB
  • Load Test: 20 Virtual Users (VUs), 30s

⚡ Benchmark Results

Framework Avg Latency (ms) Median Latency (ms) Requests/sec P95 Latency (ms) P99 Latency (ms)
FASTRAPI 0.59 0.00 31360 2.39 11.12
FastAPI + Guvicorn (workers: 1) 21.08 19.67 937 38.47 93.42
FastAPI + Guvicorn (workers: 16) 4.84 4.17 3882 10.22 81.20

TLDR; FASTRAPI can handle thousands of requests per second with ultra-low latency , making it ~6× faster than FastAPI + Guvicorn.

Comparison: FastAPI vs FastRAPI

Area FastAPI FastRAPI FastRAPI wins?
Dependency resolution Runtime inspect + reflection every request One time parsing at startup, pre-built injection plan later 🟢
fast path for trivial endpoints No cases and full kwargs/dependency work always at runtime mini compiler to skip deps, validation, kwargs, middlewares if required at startup 🟢
Route lookup speed Starlette regex router (slows with many routes) papaya concurrent hashmap + radix trie lookup 🟢
Middleware usability (Python) @app.middleware often buggy / limited working decorator + tower-http api 🟢
Background tasks reliability Fire 'n forget, errors usually swallowed proper JoinHandle + error logging 🟢
WebSocket implementation Starlette (solid but heavy) custom with bounded channels + clean async pump 🟢
Startup-time error detection Almost everything deferred to runtime Full signature + dependency analysis at decorator time 🟢
Deployment footprint Heavy (uvicorn + many deps) tiny Rust binary 🟢
Scaling to 10,000+ routes Noticeable slowdown Stays fast thanks to hashmap lookup 🟢
JSON serialization speed slow fast thanks to sonic-rs 🟢
Prometheus metrics endpoint No Yes 🟢
app.mount() / StaticFiles Yes Full support 🟢
Exception Handlers (@app.exception_handler) Yes, global error catching Full support (plus Axum .fallback() alias) 🟡
APIRouter + include_router() Yes, mature ecosystem Full support 🟡
StreamingResponse / SSE Yes, chunked streaming Full support (async & sync generators) 🟡
Frontend serving support (React, Vue, Svelte, etc.) Yes Yes 🟡
Global State (request.app.state) Yes Full support 🟡
response_model=None + raw Response return Fully supported serialization 🔴 (for now)
Concurrency & resource safety asyncio + threadpool Native Tokio + Rust memory & thread safety 🔴 (slow due to context switches)

Current Limitations

Some advanced features are still in development like:

  • Add ORJSONResponse / UJSONResponse
  • Add headers, media_type, background params to response wrapper classes
  • Add HTTPSRedirectMiddleware
  • Actually use generate_unique_id_function to generate operation IDs
  • Support yield-based dependencies (setup/teardown, e.g. def get_db(): yield db; db.close())
  • Support Annotated[Type, Depends(...)] / Annotated[str, Query(...)] style DI
  • Execute app-level dependencies=[...] on every route
  • Execute router-level dependencies=[...] from include_router/nest/APIRouter(dependencies=...)
  • Add app.dependency_overrides for testing
  • Dispatch custom @app.exception_handler(X) handlers instead of only special-casing PyHTTPException
  • Make app.state persistent across requests (not rebuilt per-request scope)
  • Fix injected Request objects to have working receive/send so .body()/.json() work
  • Add url_for()
  • Expose request.session accessor for SessionMiddleware
  • Return structured validation errors ([{"loc": [...], "msg": ..., "type": ...}]) for path/query/header/cookie params, not just Pydantic body errors
  • Support repeated query-key list params (?tags=a&tags=bList[str])
  • Support repeated form-key list params
  • Improve scalar coercion for List[int], Union/Optional, and other complex annotations
  • Implement response_model_include
  • Implement response_model_exclude
  • Implement response_model_by_alias
  • Implement response_model_exclude_unset
  • Implement response_model_exclude_defaults
  • Implement response_model_exclude_none
  • Add FileResponse
  • Add Jinja2Templates equivalent
  • Support mounting sub-applications (not just PyStaticFiles) via app.mount()
  • Support arbitrary Starlette-style ASGI middleware classes
  • Support custom route_class
  • Logging middlewares
  • Async Middleware support
  • Full middleware ordering control
  • Better error handling (currently shows Rust errors)
  • Proper Python-friendly error pages (no Rust tracebacks in production)
  • GraphQL support
  • Hot reloading / watchfiles integration
  • Built-in TestClient (starlette.testclient style)
  • Advanced dependency scopes (request vs function)
  • Rust to Python FFI helpers

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  • Fork the repository
  • Create your feature branch (git checkout -b feature/amazing-feature)
  • Commit your changes (git commit -m 'Add some amazing feature')
  • Push to the branch (git push origin feature/amazing-feature)
  • Open a Pull Request

Check out CONTRIBUTING.md for more details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Inspired by FastAPI Built with PyO3 and Axum

Star History

Star History Chart

About

⚡FastAPI alternative for Python, but actually (~6x) FASTER. Written in Rust.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

99 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages