DEV Community

Kyle Rhodelander
Kyle Rhodelander

Posted on

Best Python Libraries for Building REST APIs Without a Framework in 2026

Best Python Libraries for Building REST APIs Without a Framework in 2026

If you've ever spun up a Flask or FastAPI project just to expose a handful of endpoints, you know the feeling: you spend more time configuring the framework than writing the actual business logic. In 2026, there's a growing movement among Python developers to build REST APIs without relying on a full framework at all — using lightweight, composable libraries that give you exactly what you need and nothing more.

This isn't about reinventing the wheel. It's about understanding your tools well enough to pick the right wrench for the job. Whether you're building a microservice, an internal tool, or a high-performance API that needs to squeeze every millisecond out of the runtime, going frameworkless is a legitimate and increasingly popular approach.

In this post, we'll walk through the best Python libraries for building REST APIs without a framework in 2026 — covering HTTP handling, routing, serialization, validation, authentication, and more.


Why Go Frameworkless?

Before diving into the libraries, let's be honest about the trade-offs.

The case for going frameworkless:

  • Less magic. You understand every layer of your stack.
  • Smaller footprint. Fewer dependencies mean faster cold starts and smaller container images.
  • Better composability. You pick the serializer, the router, the validator — independently.
  • Easier upgrades. When one library has a breaking change, you don't have to upgrade an entire ecosystem.

The honest trade-offs:

  • More glue code required upfront.
  • Less community documentation for specific combinations of libraries.
  • You're responsible for security defaults that frameworks often handle for you.

With that said, let's get into the good stuff.


The Core Layers of a REST API

A REST API fundamentally needs to handle these concerns:

  1. HTTP server / request-response cycle
  2. Routing
  3. Request parsing and serialization
  4. Input validation
  5. Authentication and authorization
  6. Error handling
  7. Middleware (logging, CORS, rate limiting)

Let's go layer by layer.


HTTP Servers and ASGI/WSGI Foundations

httpx + uvicorn + Raw ASGI

If you want full control, the combination of Uvicorn as your ASGI server and raw ASGI callables as your app is the most minimal starting point imaginable. Uvicorn handles the event loop and connection management; your "app" is just a Python callable.

async def app(scope, receive, send):
    if scope["type"] == "http":
        body = b'{"message": "Hello, world"}'
        await send({"type": "http.response.start", "status": 200,
                    "headers": [[b"content-type", b"application/json"]]})
        await send({"type": "http.response.body", "body": body})
Enter fullscreen mode Exit fullscreen mode

This is almost absurdly minimal, but it's a legitimate starting point for extremely simple APIs. In practice, you'll want to layer routing and parsing on top — which is where the next libraries come in.

Install Uvicorn: Uvicorn on PyPI


Starlette — The Sweet Spot for Lightweight ASGI

Starlette deserves special mention because it's not quite a framework — it's a toolkit. It gives you routing, request/response objects, middleware, background tasks, and WebSocket support without dictating how you structure your app or handle data.

FastAPI is built on top of Starlette, which tells you something about its production-readiness. But using Starlette directly means you don't get the automatic OpenAPI generation, dependency injection system, or Pydantic integration — you compose those yourself.

from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route

async def homepage(request):
    return JSONResponse({"status": "ok"})

app = Starlette(routes=[Route("/", homepage)])
Enter fullscreen mode Exit fullscreen mode

Why it's great in 2026: Starlette has matured significantly. Its middleware stack is clean, its TestClient is excellent, and it plays nicely with every other library on this list.


Routing

Routes / Manual Routing via Starlette

Starlette's built-in routing is sufficient for most use cases. For more complex route matching (especially if you're working with regex-based patterns or mounting sub-applications), the routing primitives in Starlette cover it cleanly.

parse + Custom Routers

For developers who want zero dependencies, Python's re module combined with a simple dispatch dictionary is a perfectly valid routing layer. Several open-source gists and snippets exist for this pattern. It's not glamorous, but it's transparent.


Serialization

orjson — The Fastest JSON Library in the Room

orjson is a fast, correct JSON library implemented in Rust. In 2026, it has become the de facto standard for any Python API where performance matters. It handles datetime, UUID, numpy arrays, and dataclasses natively — things the stdlib json module requires custom encoders for.

import orjson

data = {"id": 1, "created_at": datetime.utcnow()}
serialized = orjson.dumps(data)  # Returns bytes, not str
Enter fullscreen mode Exit fullscreen mode

Benchmark reality: orjson is consistently 2–10x faster than ujson or the stdlib json module depending on payload shape. For high-throughput APIs, this matters.

Install: orjson on PyPI

msgspec — Serialization + Validation in One

msgspec is one of the most exciting libraries to emerge in recent years. It provides both serialization (JSON and MessagePack) and struct-based validation, with performance that rivals Rust-based libraries.

import msgspec

class User(msgspec.Struct):
    id: int
    name: str
    email: str

user = msgspec.json.decode(b'{"id":1,"name":"Ada","email":"ada@example.com"}', type=User)
Enter fullscreen mode Exit fullscreen mode

If you're going frameworkless and don't want to pull in Pydantic, msgspec is arguably the best single library for the serialization + validation layer in 2026.


Validation

Pydantic v2 — Still the Gold Standard

Pydantic v2 rewrote its core in Rust and is dramatically faster than v1. Even without FastAPI, Pydantic is an excellent standalone validation library.

from pydantic import BaseModel, EmailStr, ValidationError

class CreateUserRequest(BaseModel):
    name: str
    email: EmailStr
    age: int

try:
    user = CreateUserRequest(**request_data)
except ValidationError as e:
    return JSONResponse(e.errors(), status_code=422)
Enter fullscreen mode Exit fullscreen mode

Pydantic v2 also supports JSON schema generation, which means you can build your own OpenAPI documentation layer if you want it.

cerberus and voluptuous — Lightweight Alternatives

For simpler validation needs, Cerberus and voluptuous are both solid choices with minimal overhead. They're dict-based validators rather than class-based, which some developers find more natural for simple APIs.


Authentication

python-jose / joserfc — JWT Handling

JWT-based auth is the most common pattern for REST APIs in 2026. joserfc is the modern replacement for python-jose, with better algorithm support and active maintenance.

from joserfc import jwt
from joserfc.jwk import OctKey

key = OctKey.import_key({"kty": "oct", "k": YOUR_SECRET})
token = jwt.encode({"alg": "HS256"}, {"sub": "user_123", "exp": ...}, key)
claims = jwt.decode(token, key)
Enter fullscreen mode Exit fullscreen mode

authlib — OAuth2, OIDC, and More

If your API needs to act as an OAuth2 resource server or handle OIDC tokens from providers like Auth0 or Okta, Authlib is the most complete Python library for the job. It works independently of any framework.


Middleware Utilities

starlette-middleware Ecosystem

Since you're likely using Starlette as your base, you get access to its middleware system. A few middleware libraries worth knowing:

  • slowapi (PyPI): Rate limiting for Starlette/ASGI apps.
  • starlette-cors: CORS middleware built into Starlette itself via CORSMiddleware.
  • structlog (docs): The best structured logging library in Python. Integrates cleanly with any async framework.
from starlette.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://yourdomain.com"],
    allow_methods=["GET", "POST"],
    allow_headers=["Authorization", "Content-Type"],
)
Enter fullscreen mode Exit fullscreen mode

Database Access

databases + SQLAlchemy Core

For async database access without an ORM, the databases library wraps async drivers (asyncpg, aiosqlite, aiomysql) with a clean query interface. Pair it with SQLAlchemy Core for query building — not the ORM, just the expression language.

asyncpg Direct

For PostgreSQL specifically, asyncpg is the fastest Python PostgreSQL driver available and can be used directly without any abstraction layer.


Putting It All Together: A Minimal Example

Here's what a real frameworkless REST API looks like using the libraries above:

import orjson
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import Response
from starlette.routing import Route
from pydantic import BaseModel, ValidationError

class CreateItemRequest(BaseModel):
    name: str
    price: float

def json_response(data, status=200):
    return Response(
        content=orjson.dumps(data),
        media_type="application/json",
        status_code=status,
    )

async def create_item(request: Request):
    try:
        body = await request.json()
        item = CreateItemRequest(**body)
    except (ValidationError, Exception) as e:
        return json_response({"error": str(e)}, status=422)

    # Your business logic here
    return json_response({"id": 1, "name": item.name, "price": item.price}, status=201)

app = Starlette(routes=[
    Route("/items", create_item, methods=["POST"]),
])
Enter fullscreen mode Exit fullscreen mode

Run it with:

uvicorn main:app --reload
Enter fullscreen mode Exit fullscreen mode

That's a production-viable REST endpoint with validation, fast JSON serialization, and a clean ASGI server — no framework required.


Tools for Testing Your Frameworkless API

httpx with anyio

httpx is the modern HTTP client for Python, and it has a built-in async test client that works perfectly with ASGI apps:

from httpx import AsyncClient
import pytest

@pytest.mark.anyio
async def test_create_item():
    async with AsyncClient(app=app, base_url="http://test") as client:
        response = await client.post("/items", json={"name": "Widget", "price": 9.99})
    assert response.status_code == 201
Enter fullscreen mode Exit fullscreen mode

When Should You Still Use a Framework?

To be fair: going frameworkless isn't always the right call.

Use FastAPI or Django REST Framework when:

  • You need automatic OpenAPI/Swagger documentation out of the box.
  • Your team includes developers who are more comfortable with conventions.
  • You're building a large API with many endpoints and complex dependency injection needs.
  • Time to ship matters more than runtime performance.

Go frameworkless when:

  • You're building a focused microservice with 5–20 endpoints.
  • Container image size and cold start time are critical.
  • You want to deeply understand your stack.
  • You're building something that doesn't fit neatly into a framework's opinions.

Summary: The 2026 Frameworkless Python API Stack

Layer Recommended Library
ASGI Server Uvicorn
HTTP Toolkit Starlette
JSON Serialization orjson or msgspec
Validation Pydantic v2 or msgspec
Authentication joserfc + authlib
Rate Limiting slowapi
Logging structlog
Testing httpx + anyio
Database (async) asyncpg / databases

Call to Action

Ready to build your first frameworkless Python API? Start small: pick one endpoint from an existing project and rebuild it using Starlette + orjson + Pydantic v2. You'll likely be surprised by how little code it takes — and how much you learn about what your framework was doing under the hood.

Have a favorite library that didn't make the list? Drop it in the comments below. The Python ecosystem moves fast, and community knowledge-sharing is how these hidden gems get discovered.

If you found this post useful, consider sharing it with your team or bookmarking it for your next API project. And if you want to go deeper on async Python patterns, subscribe to the newsletter — we publish new deep-dives every two weeks.

Happy shipping. 🐍

Top comments (0)