Why Your Python Web App Deserves a Rust Core: Lessons from Building JustAPI
Let me start with a question that kept one developer up at night: Why does your Python web framework spend so much time doing things that have nothing to do with your code?
FastAPI sits on Starlette, which sits on uvicorn, which wraps an asyncio event loop that juggles everything between the socket and your handler. Every request—before it even reaches your business logic—crosses multiple Python boundaries, triggers serialization in Python, and gets routed through Python code that runs the same way for every single request.
What if that changed? What if the framework—the part that does identical work regardless of your application—lived entirely in Rust, and Python only ran the code that's actually unique to what you're building?
That's the premise behind JustAPI, and after spending time with the project, I think it's worth understanding not just what it does, but why the architecture decisions matter for your next project.
The Performance Story Isn't What You Think
Before diving into architecture, let's talk numbers—because performance claims without context are marketing, not engineering.
The project hit 766,000 requests per second on a basic hello-world fixture. The router performs lookups in roughly 51 nanoseconds on a 500-route configuration. Async throughput improved 14× after moving to multi-threaded Tokio with free-threaded CPython support.
Here's what those numbers actually mean for you: if you're running an API that processes thousands of requests per second, these improvements compound. Lower latency means your users wait less. Higher throughput means your servers handle more load. But the real story isn't the raw numbers—it's what you don't have to manage.
No uvicorn. No Gunicorn. No ASGI middleware stack to debug when something goes wrong at 3 AM. The entire request pipeline lives in Rust, and your Python code is just... your code.
The Architecture: Python as the Exception, Not the Rule
The request path looks like this: Kernel (epoll/io_uring) → Tokio connection manager → TLS via rustls → HTTP parsing via Hyper → Router (matchit radix trie) → Middleware chain (auth, CORS, rate-limiting) → Python boundary via PyO3 → Your handler → Rust serializer → Response.
Notice where Python enters: only at the point where your application logic begins. Everything before that—everything that runs identically for every request—is Rust.
This is an important distinction. The developer behind JustAPI imposed a simple rule during development: if a feature can be implemented in Rust, it must be implemented in Rust. Not "can be faster in Rust"—can be implemented in Rust. Python is reserved for the glue between Rust values and your handlers.
It's a constraint that shaped the entire project and resulted in something genuinely different from other Python frameworks that have bolted on Rust pieces.
What This Means for Developer Experience
Here's where I think this approach gets interesting for startups and growing teams.
You get a complete API framework—HTTP/1.1 and HTTP/2, TLS, routing with parameters, JSON serialization, automatic OpenAPI documentation—with 30 lines of code that actually look like Python:
from justapi import JustAPIApp
app = JustAPIApp()
@app.get("/")
def hello():
return {"Hello": "World"}
app.run()
But underneath that familiar surface, you're running a Rust server that handles TLS, manages connections, and serializes responses without ever crossing into Python. The developer experience stays Pythonic. The runtime performance is Rust.
For teams building MVPs that might need to scale later, this matters. You write Python today. You get Rust performance without rewriting anything when you need to handle more load.
The AI Factor: An Engineering Partner, Not a Replacement
This project was built with agentic AI as an active participant—not as autocomplete, but as an engineering guide that helped design the architecture, turn decisions into code, find bugs, and write tests.
That's worth discussing honestly, because it's increasingly common and rarely talked about transparently.
The developer describes the codebase in three tiers: parts he understands completely, parts he understands well enough to maintain, and parts AI wrote that he reviewed and tested but couldn't reproduce from memory. He's upfront that this is part of how the project exists.
I think that's the right framing. AI tools are accelerating development on complex projects, and pretending otherwise helps no one. The key is understanding what you own versus what you've delegated—and being honest about which is which.
The Practical Takeaway
Frameworks like JustAPI represent a shift in how we're thinking about Python's role in high-performance systems. Python isn't going anywhere for application logic—its readability and ecosystem are too valuable. But the assumption that the framework itself has to run in Python is being challenged.
Whether JustAPI becomes your next framework or remains an interesting experiment, the underlying insight has value: look at what runs the same on every request in your stack. That's probably Rust territory. The parts that change? Keep those in whatever language your team is most productive in.
The gap between "works" and "works well" keeps narrowing. Your users won't notice the architecture, but they'll notice the latency.
Looking Forward
JustAPI is at version 2.0.10 with documented features including WebSockets, SSE, background tasks, a scheduler, database access via SQLx, and operational tooling like OpenTelemetry and Prometheus metrics. It's available on PyPI with wheels for standard Linux, macOS, Windows, and the free-threaded CPython 3.14t build.
The numbers are in the repository. The tests pass. The failures are documented. That's the kind of engineering transparency we should encourage more of.
If you're building Python APIs and performance matters to you, it's worth a look. The future of Python web frameworks might not look like what you're using today.