/ justapi / README.md
swadhinbiswas πŸ“ docs: modern README with animated SVG hero, pipeline, benchmark, feature matrix Β· 8/7/2026
4322714
346 lines Β· 14.1 KB
Raw Download

JustAPI β€” Python writes the logic. Rust does everything else.

CI Wheels & Release PyPI Python Rust MIT Free-threaded cargo-deny


JustAPI is a Python web framework with a Rust core. You write Python logic.
Rust handles everything else β€” networking, TLS, routing, validation,
serialization, SSE, database I/O, rate limiting. One pip install, a server
that starts in milliseconds, and numbers that hold up under real traffic.

Python writes the logic. Rust does everything else.


Quickstart

pip install justapi
# main.py
from justapi import JustAPIApp

app = JustAPIApp()

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

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}

app.run()
$ python main.py
INFO:     JustAPI running on http://127.0.0.1:8000

Interactive OpenAPI docs at http://127.0.0.1:8000/docs β€” generated from your code, zero configuration.

Async? Native. DB? Native. SSE? Native.

import asyncio
from justapi import JustAPIApp, native_async

app = JustAPIApp()
app.set_database("postgres://user:pass@host/db")
app.sse_native("/events", count=1000, interval_ms=0)   # Rust streams events β€” 0 Python per event

@app.get("/users/{uid}")
@native_async
async def get_user(request, uid: int):
    row = await app.db.query_async(                     # runs on the DB's tokio runtime
        "SELECT * FROM users WHERE id = ?", [uid])      # GIL released β€” loop never blocks
    return row

app.run()

Performance

Benchmark β€” JustAPI vs Granian vs FastAPI vs Robyn

Hello-world, 100 concurrent connections, 30s, same hardware. Full methodology in BENCHMARKS.md.

Framework Hello-world JSON echo p99 hello-world RSS
JustAPI (native fast path) 766k req/s 782k req/s 0.48 ms 12 MB
Granian (ASGI) 314k 145k 0.74 ms 37 MB
Robyn 39k β€” β€” β€”
FastAPI + Uvicorn 36k 33k 24.63 ms 29 MB

More numbers, honestly:

  • Route lookup: 51 ns average on a 500-route table (matchit radix trie)
  • Rust-native CRUD: 181k SELECT req/s β€” Γ—125 vs FastAPI on the same DB fixture
  • Native async DB awaits (query_async): 53Γ— faster than the blocking path on slow queries (320 vs 6 RPS) β€” the asyncio loop is never blocked
  • Multi-worker prefork (justapi serve --workers N): 1.88Γ— throughput at 4 workers (99.7k RPS), auto-scale included
  • Free-threaded CPython (3.14t): CPU-bound Python handlers 12.4Γ— faster β€” the GIL ceiling is gone

Honest caveats

  • Native fast path requires a schema. Routes without a Schema fall back to the Python handler path (~60k req/s). The ~700k numbers apply to routes with native=True + Schema.
  • Python handler throughput is GIL-bound. On GIL-locked CPython, the Python dispatch path caps at ~100-120k req/s on this hardware regardless of framework β€” that is the GIL, not a framework limitation. Free-threaded Python (3.14t) removes this ceiling.
  • Light async handlers are loop-bound. Async handlers that only sleep/echo (~4-12k req/s) are capped by the asyncio loop + thread hop. Three experiments (ADR-090/091/092) proved no coroutine driver, bridge, or multi-loop approach beats asyncio's own stepping. We win where it matters: real async workloads (1ms-sleep handlers: 3.9k vs Granian 2.9k RPS) and anything DB/SSE-heavy via native ops.
  • LLM-serving claims are NOT part of this release. Inference phases are unverified (no real GPU run, ADR-067) β€” the tested story is the web framework.

How a request flows

Request pipeline β€” Rust end to end

The entire request path runs in Rust. Python executes only your application logic:

Kernel (epoll/io_uring)
  β†’ tokio connection manager
  β†’ TLS (rustls)
  β†’ HTTP parse (hyper)
  β†’ Router (matchit, 51ns)
  β†’ Middleware chain (auth, CORS, rate-limit, compression)
  β†’ Python boundary (zero-copy PyO3, GIL pool)
  β†’ Your async Python handler
  β†’ Rust serializer (serde_json / simd-json)
  β†’ Response write β†’ socket

Routes marked native=True + Schema skip Python entirely β€” Rust validates the
body and writes the response. That is the ~700k req/s path.


Feature highlights

Feature matrix

CategoryFeatureDetails
Performance HTTP/1.1 Β· HTTP/2 Β· HTTP/3~766k req/s native fast path; QUIC (HTTP/3) is feature-gated β€” no other Python framework ships it
TLS (rustls)~10% overhead, zero OpenSSL dependency
Serializationserde_json with optional simd-json (89 ns/op)
Compressiongzip / deflate / brotli / zstd
Multi-worker preforkjustapi serve --workers N --scale β€” shared-socket process fleet with load-based auto-scaling
Native ops Async DB awaitsawait app.db.query_async() β€” SQL on the DB's tokio runtime, GIL released, loop never blocked (ADR-093)
Rust-native CRUDRust validates + queries + serializes β€” 181k SELECT req/s, Γ—125 vs FastAPI
Native SSEapp.sse_native(path, count, interval_ms) β€” events generated in Rust, zero Python per event
@native_asyncMarks async handlers for the fastest dispatch; true parallel dispatch on free-threaded CPython
Adaptive batchingBatch + window decorator for bursty workloads
Security JWT AuthenticationHS256/RS256/ES256, per-route roles & scopes, OAuth2 password flow
Rate LimitingGCRA, Redis-backed distributed, IP + per-route
CORSConfigurable, preflight caching
Request ValidationJSON Schema compiled in Rust, Pydantic v2 bridge
Security HeadersHSTS, CSP, X-Frame-Options, nosniff, and more
Protocols RESTFull HTTP methods with OpenAPI 3.1
WebSocketFull-duplex with streaming support
Server-Sent EventsGenerator-driven + Rust-native streaming
gRPCNative Tonic integration
GraphQLasync-graphql wiring
Application Dependency InjectionLitestar-style tiered DI, sync/async generators, cleanup
Background TasksThread-safe task scheduling
DatabaseSQLite / PostgreSQL / MySQL / DuckDB via sqlx β€” pool, migrations, transaction middleware
Template EngineJinja2 integration
File UploadsStreaming multipart/form-data
Operations ObservabilityOpenTelemetry tracing, Prometheus metrics, health checks
ResilienceCircuit breakers, retry, fallback, bulkhead β€” 44 resilience tests
Hot Reloadjustapi serve --reload with graceful drain
Plugin SystemThird-party extension API with lifecycle hooks
WASM Pluginswasmtime-powered WebAssembly middleware
DX & Quality Type Stubspy.typed + complete .pyi β€” mypy-clean on user code
Scaffoldingjustapi create β€” full CRUD project (7 DB backends, 4 API styles) that demos every differentiator
Memory SafetyASan on the full suite + Miri on all unsafe code, 6 fuzz targets
Supply Chaincargo-deny β€” advisories, bans, licenses, sources

Coming from FastAPI?

JustAPI mirrors FastAPI's decorator API and Pydantic integration, so existing
apps migrate with minimal changes β€” often just the import:

FastAPI JustAPI
Import from fastapi import FastAPI from justapi import JustAPIApp
Create app = FastAPI() app = JustAPIApp()
Decorators @app.get("/items/{id}") @app.get("/items/{id}")
Pydantic Native Native
Depends() Built-in Built-in (incl. generator deps + cleanup)
OpenAPI /docs and /redoc /docs and /redoc
Server uvicorn (Python) Built-in Rust server (tokio + hyper)
Hello-world ~36k req/s ~766k req/s (native fast path)

πŸ‘‰ Full migration guide.


Architecture

justapi/
β”œβ”€β”€ crates/
β”‚   β”œβ”€β”€ justapi-core/       # Networking, routing, middleware, serialization
β”‚   β”œβ”€β”€ justapi-py/         # PyO3 bindings + Python package (python/justapi)
β”‚   β”œβ”€β”€ justapi-cli/        # CLI binary (serve, create, check, gen-client)
β”‚   └── justapi-bench/      # Internal benchmark harness
β”œβ”€β”€ assets/                 # README diagrams (animated SVG)
β”œβ”€β”€ benchmarks/             # Workload scripts for baseline comparisons
β”œβ”€β”€ docs_site/              # Full documentation site (141 pages)
β”œβ”€β”€ skills/                 # Reusable engineering knowledge
β”œβ”€β”€ PLAN.md                 # Living roadmap (single source of truth)
β”œβ”€β”€ DECISIONS.md            # Append-only ADR log
└── BENCHMARKS.md           # Append-only performance ledger

Crate dependency graph:

justapi-cli  ──→  justapi-core
justapi-py   ──→  justapi-core
justapi-bench ─→  justapi-core

Development

Prerequisites

Build & test

cargo build --workspace --release
cd crates/justapi-py && maturin develop --release   # build the Python package

cargo test --workspace                              # Rust tests
cargo clippy --workspace --tests -- -D warnings     # lint
cargo fmt --check                                   # format
cargo deny check                                    # supply-chain audit
bash scripts/sanitize.sh                            # ASan + Miri memory-safety gate
python -m pytest                                    # Python tests (in the venv)

Benchmark

bash benchmarks/run_baselines.sh                    # FastAPI / Granian / JustAPI A/B

See BENCHMARKS.md for methodology, hardware, and history.


Deployment

# Docker (multi-stage, uv-based β€” fast reproducible builds)
docker build -t justapi-app .
docker run -p 8000:8000 justapi-app

# Multi-worker + auto-scale (saturate all cores)
justapi serve --workers 4 --scale
  • Kubernetes: helm install my-api helm/justapi/ --set image.repository=your-registry/justapi-app
  • Cloud guides: EKS Β· GKE Β· AKS Β· Fly.io Β· Railway
  • Observability: OTel tracing + Prometheus metrics + health probes out of the box

Documentation

Document Description
docs_site Full documentation site β€” 141 pages, 13 sections, search
Migration guide Step-by-step from FastAPI
BENCHMARKS.md Performance ledger (append-only)
PLAN.md Living roadmap and current phase
DECISIONS.md Architecture decision records (ADR-001 β†’ ADR-093)
AGENTS.md Development conventions & review checklist

Contributing

Contributions welcome. Read AGENTS.md for conventions before opening a PR.

git clone [email protected]:swadhinbiswas/JustAPI.git
cd JustAPI
git checkout -b feat/my-feature
# ... make changes ...
cargo test --workspace
cargo clippy --workspace --tests -- -D warnings
cargo fmt --check

Every PR is gated on: tests green, clippy -D warnings, fmt clean, sanitizers
clean (core touched), benchmarks appended (perf touched), ADR recorded
(architecture touched).


License

MIT Β© JustAPI contributors