Skip to main content

QUIC-based RPC library with Python bindings

Project description

Knafeh

A high-performance QUIC-based RPC framework written in Rust with first-class Python bindings.

Knafeh provides two transport backends — raw QUIC (quinn) for maximum throughput and HTTP/3 (tokio-quiche) for gRPC compatibility — with pluggable codecs, middleware, server-streaming, and connection pooling.

Features

  • Dual transport — Raw QUIC (~13K rpc/s) or HTTP/3 (~4K rpc/s), selectable per use case
  • Pluggable codecs — Protobuf (default), JSON, or implement the Codec trait
  • Unary & server-streaming RPCs — with length-prefixed framing for HTTP/3 streams
  • MiddlewareInterceptor trait for auth, logging, tracing, rate limiting
  • Connection pooling — QUIC-native multiplexing with automatic reconnection
  • RetriesRetryPolicy with exponential backoff, jitter, status-code awareness
  • Python bindings — Native async (pyo3-async-runtimes) + sync API, anyio structured concurrency
  • gRPC-compatible status codes — 17 standard codes with proper error propagation

Quick Start

Prerequisites

  • Rust 1.94+
  • Python >= 3.13 (for Python bindings)
  • maturin (for building Python wheels)

Generate TLS Certificates

QUIC requires TLS. For development, generate a self-signed cert:

openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
    -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'

Tests generate certs automatically via rcgen — no manual setup needed.

Rust — HTTP/3 Server + Client

use knafeh::server::Server;
use knafeh::codec::JsonCodec;
use knafeh::transport::tls::TlsConfig;

let server = Server::builder()
    .bind_str("0.0.0.0:4433")?
    .tls(TlsConfig::server("cert.pem", "key.pem"))
    .codec(JsonCodec::new())
    .add_service(my_service)
    .build()?;

server.serve().await?;
use knafeh::client::Client;
use knafeh::codec::JsonCodec;

let client = Client::builder()
    .endpoint("localhost:4433")
    .codec(JsonCodec::new())
    .build()
    .await?;

let response = client.call("greeter/say_hello", body).await?;

Rust — Raw QUIC (maximum performance)

use knafeh::transport::quic_native::{QuicClient, QuicServer};

// Server
let server = QuicServer::bind(addr, &cert_pem, &key_pem, router, codec, middleware)?;
server.serve().await?;

// Client
let client = QuicClient::connect_insecure(addr, codec, middleware).await?;
let response = client.call("echo/echo", body).await?;

Python — Async Client

from knafeh import Client, TlsConfig

async with Client("localhost:4433", tls=TlsConfig.client_insecure()) as client:
    response = await client.call("greeter/say_hello", b'{"name": "World"}')

    # Batch concurrent calls with structured cancellation (anyio TaskGroup)
    responses = await client.call_many("echo/echo", [b'msg1', b'msg2', b'msg3'])

Python — Sync Client (scripts, notebooks)

from knafeh import SyncClient

with SyncClient("localhost:4433") as client:
    response = client.call("echo/echo", b"hello")
    for chunk in client.server_stream("count/count", b'{"count": 5}'):
        print(chunk)

Python — Server

from knafeh import Server, TlsConfig

server = Server("0.0.0.0:4433", tls=TlsConfig.server("cert.pem", "key.pem"))

@server.service("greeter")
class Greeter:
    def say_hello(self, request: bytes) -> bytes:
        import json
        name = json.loads(request)["name"]
        return json.dumps({"message": f"Hello, {name}!"}).encode()

await server.serve()

Building & Testing

# Rust crate (Python bindings are opt-in via the python feature)
cargo build
cargo test

# Python
uv sync --python 3.13 --group dev
PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 uv run maturin develop --features python
uv run pytest tests/test_knafeh.py -v

# Performance benchmarks (release mode)
cargo test --no-default-features --release --test e2e_perf_test -- --ignored --nocapture

TLS certificates are generated at runtime via rcgen — no manual cert setup needed for tests.

Releasing

Releases are published by the GitHub Actions release workflow when a semver tag like v1.0.0 is pushed. Before tagging, update the matching versions in Cargo.toml and pyproject.toml. For an existing tag, run the workflow manually and provide the tag value.

Required repository secrets:

  • CARGO_REGISTRY_TOKEN for crates.io
  • PYPI_TOKEN for PyPI

The workflow publishes the Rust crate and Linux x86_64 PyPI wheels for Python 3.13 and 3.14.

Performance

Benchmarked on localhost, release mode, 10K sequential requests:

Transport Throughput p50 Latency
Raw QUIC (quinn) 12,680 rpc/s 76 us
HTTP/3 (tokio-quiche) 4,300 rpc/s 230 us

Parallel (32 in-flight): Raw QUIC reaches 104K rpc/s, HTTP/3 reaches 15K rpc/s.

See docs/E2E_TESTING_REPORT_v1.0.0.md for full benchmark results including codec comparisons, Python client/server benchmarks, and external framework comparisons.

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

knafeh-1.1.0-cp314-cp314-manylinux_2_34_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ x86-64

knafeh-1.1.0-cp313-cp313-manylinux_2_34_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

File details

Details for the file knafeh-1.1.0-cp314-cp314-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for knafeh-1.1.0-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 b2a0f3e2f08bfdecbb770e929bcc7f04bc8d8b534c89cec8dbc399d31a9f70e9
MD5 2b3d8ac4be7e56f9ff9c0d7d929a6de0
BLAKE2b-256 a9744727070350dfe18af9a39d7cece0e78bc1c5071e7d4989864d53f0a09575

See more details on using hashes here.

File details

Details for the file knafeh-1.1.0-cp313-cp313-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for knafeh-1.1.0-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 d6746f636f38762f9ab737160136117e3495cad5c705b49b5ce072d0b5e4fd1f
MD5 05da2f1d8d733f7c00c3aeb7b3bbf413
BLAKE2b-256 d5027b3689aeaa316d42375c71f0b53c0666cae2b0974b1d9eaec38619e7dab5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page