Skip to main content

Korvex

CI License: MIT

A fast router for Python, written in Rust, with an optional ASGI app on top.

Korvex is young (alpha). Its routing is fast (see Performance), but it lacks some of what full frameworks offer: WebSockets, validation, OpenAPI. The roadmap lists what's coming.

pip install korvex

The router

Router maps a path and an HTTP method to a handler name. It never calls your code: what you do with the name is up to you.

from korvex import Router

router = Router()
router.get("/users/{id:int}", "get_user")
router.post("/users", "create_user", middleware=["auth"])

router.match("/users/42")         # ("get_user", {"id": 42}, ())
router.match("/users", "POST")    # ("create_user", {}, ("auth",))
router.match("/nope")             # None
router.match("/users", "DELETE")  # raises MethodNotAllowed, .allowed == ["POST"]

Path syntax

Segment Matches Example
users exactly users /users
{id} any segment /users/{id}
{id:int} an integer (42, -7) /users/{id:int}
{id:uuid} a UUID /items/{id:uuid}
*path the rest of the path (last segment) /static/*path

{id:int} gives an int and {id:uuid} a uuid.UUID; every other captured value is a string. When several routes could match, the most specific one wins: literal, then {id:int}/{id:uuid}, then {id}, then *path.

API

Method Does
route(path, handler, *, method="GET", middleware=None) Registers a route (replaces an existing one).
get / post / put / patch / delete / head / options(path, handler, *, middleware=None) Shortcuts for route.
match(path, method="GET") (handler, params, middleware), None, or raises MethodNotAllowed.
remove(path, method="GET") Removes a route by its pattern. Returns whether it existed.
routes() Every route as (path, method, handler, middleware).
group(prefix, *, middleware=None) A RouteGroup (see below).

Invalid paths or methods raise ValueError.

match keeps the last 1,024 distinct lookups in a cache, and adding or removing a route clears it. Its results are shared between calls, so they are immutable: params is a read-only mapping and middleware a tuple.

Route groups

api = router.group("/api", middleware=["auth"])
api.get("/users", "list_users")             # GET /api/users, middleware ("auth",)

admin = api.group("/admin", middleware=["admin"])
admin.get("/stats", "stats")                # GET /api/admin/stats, middleware ("auth", "admin")

The ASGI app

App runs the matched handler for you. Serve it with any ASGI server (uvicorn, hypercorn, granian...).

from korvex import App, Response

app = App()

@app.get("/users/{id:int}", middleware=["auth"])
async def get_user(request, id):
    return Response.json({"id": id})

@app.middleware("auth")
def auth(request):
    if request.headers.get("Authorization") is None:
        return Response.text("Unauthorized", status=401)  # stops here
    return None                                          # carries on
pip install "korvex[serve]"   # installs uvicorn
uvicorn mymodule:app
  • Handlers receive the Request plus path params as keyword arguments, and return a Response. Middleware returns a Response to answer early, or None to continue. Both can be sync or async.
  • Request has method, path, headers, query_params, path_params, cookies, and await request.body(), await request.json(), await request.form(). A form maps each field to its values; files from a multipart form are UploadedFiles (filename, content_type, data). A body that can't be parsed is answered with a 400.
  • Response(body, status=, headers=), Response.text(...), Response.json(...), Response.redirect(...), and response.set_cookie(...) / response.delete_cookie(...).
  • Response.stream(chunks) sends a body piece by piece, from a sync or async generator. Response.file(path, filename=None) sends a file in chunks (with filename, as a download). app.static("/static", "public") serves a directory; paths that leave it get a 404.
  • HEAD requests are answered by the GET route, without the body.
  • Unknown paths get a 404; known paths with the wrong method get a 405 with an Allow header.
  • raise HTTPException(404, "user not found") in a handler or middleware answers with that error. @app.exception_handler(404) (a status) or @app.exception_handler(ValueError) (an exception class) customizes the response. Any other exception gives a 500 and is logged to the korvex logger.
  • app.group(prefix, middleware=[...]) works like router.group(), with decorators: api = app.group("/api"), then @api.get("/users"). Groups nest.
  • Routes registered on app.router directly are linked to a function with @app.handler("name").
  • @app.on_startup and @app.on_shutdown run a function (sync or async) when the server starts and stops, for example to open and close a database pool. Shutdown hooks run in reverse order. If a startup hook raises, the server doesn't start. Both @app.on_startup and @app.on_startup() work.

More in examples/. To put it in production (behind nginx or Caddy, in Docker, on AWS Lambda or Vercel), see the deployment guide.

Performance

Under load

The same small app (1,000 routes, one JSON endpoint) in each framework, served the same way (uvicorn, one worker, one CPU core) and flooded with requests to random URLs by oha:

Requests per second on one CPU core with 200 clients: Korvex 33.7k, Starlette 3.0k to 30.6k, Falcon 30.5k, Litestar 18.2k, Sanic 15.8k, FastAPI 1.6k to 12.4k, BlackSheep 6.7k, Django 1.1k to 2.2k.
Framework Requests/s, 200 clients p99 latency, 1,000 clients RAM at rest, peak
Korvex 33.7k 26 ms 35 MB, 46 MB
Starlette 3.0k to 30.6k 35 to 189 ms 39 MB, 49 MB
Falcon 30.5k 31 ms 60 MB, 63 MB
Litestar 18.2k 79 ms 78 MB, 89 MB
Sanic 15.8k 94 ms 60 MB, 105 MB
FastAPI 1.6k to 12.4k 57 to 351 ms 66 MB, 77 MB
BlackSheep 6.7k 70 ms 51 MB, 59 MB
Django 1.1k to 2.2k 1.3 to 1.9 s 48 MB, 145 MB
  • Every framework uses a full CPU core under load, so requests per second is also how much work each one gets out of that core.
  • Falcon, and Starlette in its best case, come within about 10% of Korvex.
  • Starlette, FastAPI and Django try routes one by one: the ranges go from the tested route declared after the 1,000 others to declared first. BlackSheep tries them one by one too, but sorts them itself, deepest first, so here the tested route always comes last.
  • No request failed. Throughput holds steady as clients are added; latency grows because requests queue, not because each one gets slower. After the flood, memory stays flat and speed is back to normal.

Robyn isn't included: it runs its own server, so it wouldn't be the same comparison. Korvex plans its own built-in server (see the roadmap), and the two will be compared then.

Reproduce with uv run python benches/load_test.py (needs cargo install oha, takes about 11 minutes).

Router alone

Route matching only, without any server:

Time per route lookup at 10,000 routes. Without cache: Korvex 347 ns, Litestar 732 ns, Sanic 3.5 µs, Flask 3.5 µs, Django 1.3 ms, Starlette 1.5 ms. With each router's cache and repeated URLs: Korvex 67 ns, Litestar 92 ns, Sanic 211 ns.

Median time per lookup, 10,000 routes:

Router First time a URL is seen Same URL again (cached)
Korvex 347 ns 67 ns
Litestar 732 ns 92 ns
Sanic 3.5 µs 211 ns
Flask 3.5 µs (no cache)
Django 1.3 ms (no cache)
Starlette / FastAPI 1.5 ms (no cache)
  • Korvex is the fastest in both cases, and its time stays flat as routes are added. Django and Starlette try routes one by one, so they slow down linearly.
  • Korvex, Litestar and Sanic cache the last 1,024 lookups. The cache helps most with static URLs; URLs with parameters (/users/1, /users/2, ...) are often different, so they hit it less.
  • With few routes, the server and the handler cost more than the router. With many routes, a router that tries them one by one becomes the main cost (see Under load).

Reproduce with uv run pytest benches/bench_router.py --benchmark-only --benchmark-json=benches/results.json, then uv run python benches/plot.py to redraw both charts. Results depend on the machine: measure your own workload before relying on any number.

Development

uv run maturin develop --release   # build the Rust extension
uv run pytest                      # Python tests
cargo test                         # Rust tests

See CONTRIBUTING.md, and ROADMAP.md for what's planned.

License

MIT

Metadata

Release files for korvex 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for korvex 0.4.0
File Size Uploaded Provenance Actions
korvex-0.4.0.tar.gz 201.7 kB With provenance Details for korvex-0.4.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for korvex 0.4.0
File Actions
korvex-0.4.0-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details for korvex-0.4.0-cp39-abi3-win_amd64.whl
korvex-0.4.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details for korvex-0.4.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
korvex-0.4.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details for korvex-0.4.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
korvex-0.4.0-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details for korvex-0.4.0-cp39-abi3-macosx_11_0_arm64.whl
korvex-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl CPython 3.9 abi3 macOS 10.12+ x86-64 Details for korvex-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl

Total release size: 1.6 MB

Release files / korvex-0.4.0.tar.gz

Download URL korvex-0.4.0.tar.gz
Size 201.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c84f57b7adc91b4654846cd87b041adcae33a9e8a2bb0a611e3f0d650d7cb36d
BLAKE2b-256 checksum
How to use checksums
f35815ce2fbe244ac601bf5eb0aea2ed1249972f43680804e40b5c9098bbdcb4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Release files / korvex-0.4.0-cp39-abi3-win_amd64.whl

Download URL korvex-0.4.0-cp39-abi3-win_amd64.whl
Size 177.6 kB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
731b3e2c7a892597250f2590ce8e9fe947e5c926e947bcb6c008783db4d43848
BLAKE2b-256 checksum
How to use checksums
b604441ffebf93267c88b61dd3caf2df4f06e5c7c41da58e82cac263a3958544
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Release files / korvex-0.4.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL korvex-0.4.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 323.7 kB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
517bf3294a018e81a9212a68af12dca4786146d40feeb2c8e88a79f60ca0efb5
BLAKE2b-256 checksum
How to use checksums
f9afa81e05d7bfbe1f05394dc73125c45a2661d91a4083c45de6a45cbb464694
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Release files / korvex-0.4.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL korvex-0.4.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 318.4 kB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
0b605cdfa94d1491a10a6a0a2b3f4cd69aeac88408bbed7ee1836b805b075e74
BLAKE2b-256 checksum
How to use checksums
9e5dd4c502c81a3b103117c876e38c56117d515fc16eb5044e998cd8b5a24606
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Release files / korvex-0.4.0-cp39-abi3-macosx_11_0_arm64.whl

Download URL korvex-0.4.0-cp39-abi3-macosx_11_0_arm64.whl
Size 284.2 kB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a729bae6f23df25e389fbbffac8f917cd8d1b3ba036540c237159770d92ce0ff
BLAKE2b-256 checksum
How to use checksums
33f0e1906455bff0236f72a19b71e7232b921d5ab46de1e0527fcb690fefa8d4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Release files / korvex-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl

Download URL korvex-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl
Size 283.3 kB
Tags CPython 3.9 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
e48c0a2a3764309a2d256642c48c70d5b5d38a838e59e5087acad9cc911b6518
BLAKE2b-256 checksum
How to use checksums
0cb09050f5a442b96f0712973a349e10587b38897d84617367e5a59f831339f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Security for korvex 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for korvex-0.4.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page