0.4.0 One network stack: Rama

Portus API & AI Gateway

A fully conformant Kubernetes gateway, built in Rust for speed. It carries your HTTP, LLM and MCP traffic on one data plane.

$helm install portus oci://ghcr.io/portus-gateway/charts/portus-gateway
Quick start →
ClientsPortusYour Services
HTTP · gRPC · TLSLLMMCP
measured 224,173 req/s · p99 2.98 ms at 256 connections
130/130
Gateway API v1.6.2 conformance tests. No skips.
224k
Requests per second through 3 proxy pods at 256 connections
2.98ms
p99 latency at 224,000 requests per second
133k
1 KB responses per second through 3 proxy pods
Portus 0.2.12 on an AWS c7a.8xlarge (32 vCPUs), medians of three interleaved rounds.
Conformance

Every test. Every profile. No skips.

Gateway API v1.6.2, experimental channel. The upstream suite runs in-cluster against a real per-Gateway deployment. Each square below is one passing result.

Request mirroringPath & host rewriteHeader modificationH2C & WebSocket backendsMethod & query matchingRequest & backend timeoutsHTTPRoute retryCORSListenerSetListener isolationBackendTLSPolicy with SAN validationTLS terminate, passthrough & mixedClient certificate validationTCPRouteUDPRoute
Performance

Fast under load. Lean on CPU.

Measured with the open gateway-api-bench method: three interleaved rounds on one machine, against the same backend pods as the top-ranked gateway in that benchmark. Every number and every round is published.

Portus 0.2.12agentgateway v1.5.0requests per second, bare GET /

p99 at 256 connections

Portus2.98ms
agentgateway3.94 ms

Errors when 1 of 4 backends goes dark

Portus0.025%
agentgateway2.0 %

Proxy CPU, download ladder

Portus4.1 cores
agentgateway5.7 cores

Method: the howardjohn/gateway-api-bench approach on an AWS c7a.8xlarge (32 vCPUs, AMD EPYC 9R14; single-node k3s, pods at MTU 65000), three interleaved rounds per gateway, fortio in-cluster with one pod per rung, 3 proxy pods each. Medians shown. Numbers from one machine are only comparable with each other. agentgateway is ahead on 1 MiB plain-HTTP downloads and uses less memory per pod. Failover figures come from the gateway-api-bench suite on Docker Desktop with no retry policy; with a RetryPolicy Portus returns 0 errors. Every round, including the tests agentgateway wins →

One data plane

Three gateways. One install.

Kubernetes routes, LLM providers and MCP tool servers sit behind the same Gateway, under the same policies, in the same Rust process.

The whole Gateway API, compiled straight to protobuf.

  • Every route kind. HTTPRoute, GRPCRoute, TLSRoute, TCPRoute, UDPRoute, ListenerSet and BackendTLSPolicy.
  • A data plane per Gateway. Each Gateway gets its own Deployment, Service and PodDisruptionBudget, with its address in status.addresses.
  • Fourteen policy CRDs. Timeouts, retries, rate limits, circuit breakers, health checks, CORS, IP allow lists, body limits, and Basic, API-key, JWT and forward auth.
  • No intermediate config language. The controller compiles your CRDs into one protobuf message and streams each Gateway its slice.
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
spec:
  gatewayClassName: portus-gateway
  listeners:
  - name: http
    protocol: HTTP
    port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-route
spec:
  parentRefs:
  - name: my-gateway
  hostnames: ["app.example.com"]
  rules:
  - backendRefs:
    - name: my-service
      port: 8080
Design

Built so the hot path stays hot.

Nothing on the request path.

Keys, budgets and token checks are local lookups against state the ledger pushes in. A request never waits on another service.

Reloads never drop a connection.

Config arrives over mTLS gRPC and swaps atomically. Each data plane acknowledges the fingerprint it applied, and that drives the Gateway's Programmed condition.

The network stack is a plug-in.

Routing, policies, TLS and the AI logic live in a stack-independent core. That let us measure two engines side by side and ship the faster one.

Architecture

From CRD to wire in one compile.

Reconcilers feed a shared store, the store compiles to a CompiledConfig protobuf, and each data plane receives only its own Gateway's slice.

Kubernetes API Gateway · HTTPRoute · GRPCRoute · TLSRoute TCPRoute · UDPRoute · AIRoute · AIProvider watch portus-controller reconcilers → ConfigStore → CompiledConfig portus-ledger keys · budgets · usage gRPC stream · mTLS snapshots · usage dataplane Gateway A · rama dataplane Gateway B · rama dataplane Gateway C · rama your services your services your services

Controller

Watches Gateway API and Portus CRDs with kube-rs, provisions a data plane per Gateway, and recompiles on any change. Reconcilers publish events to each other instead of polling.

Data plane

Builds route maps keyed by port and hostname with full Gateway API precedence. Failing endpoints are ejected passively and readmitted with back-off. SIGTERM drains in-flight requests.

Ledger

Opt-in with the AI gateway. Issues keys, keeps budgets as a shared counter synced every second, stores usage, and fetches OAuth issuers' signing keys. It never sits on the request path.

Network stack

We tested two engines. Rama won.

Everything Portus decides lives in a core that knows nothing about the proxy framework underneath. So we ran the same gateway on Rama and on Pingora, on the same machine, and measured. Rama was faster on every payload rung and used 2–2.6× less memory, so it became the default in 0.2.4 and the only stack in 0.4.0.

The data plane since 0.4.0

Rama 0.4

Used unpatched, with Portus's own upstream connection pool. 130/130 conformance, and the AI and MCP gateways run on it.

+3–31 %throughput vs Pingora, every rung
2–2.6×less memory
Removed in 0.4.0

Pingora 0.9

Cloudflare's proxy framework carried Portus through its first releases and the benchmarks above. Rama measured faster than it on every payload rung.

Rama against Pingora: a single round on the same machine, 2026-09-15.

Standalone

No cluster? Still Portus.

Point the data plane at one YAML file and it runs as a plain reverse proxy, with the same routing, policies and TLS it runs in Kubernetes.

  • ACME built in. Let's Encrypt certificates over http-01 or tls-alpn-01, renewed at two thirds of their lifetime.
  • Hot reload. Edit the YAML or renew a certificate and the change applies without a restart or a dropped connection.
  • Backends by name. Docker Compose services and VM hostnames, re-resolved every 30 seconds.
PORTUS_CONFIG_FILE=portus.yaml portus-dataplane
acme:
  email: ops@example.com
  cache_dir: /var/lib/portus/acme
  challenge: http-01

listeners:
  - port: 80
    protocol: HTTP
    routes:
      - hosts: ["secure.example.com"]
        redirect: {scheme: https, status_code: 301}

  - port: 443
    protocol: HTTPS
    tls:
      acme:
        domains: ["secure.example.com"]
    routes:
      - hosts: ["secure.example.com"]
        backends:
          - address: "web:8080"   # compose service
            weight: 3
          - address: "10.0.1.2:8080"
            weight: 1
Get started

Two commands to a conformant gateway.

Kubernetes 1.32+ · Helm 3.8+ · amd64 & arm64
# Gateway API CRDs, experimental channel
kubectl apply --server-side --force-conflicts \
  -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.2/experimental-install.yaml

# Portus: controller, GatewayClass, policy CRDs, mTLS material
helm install portus oci://ghcr.io/portus-gateway/charts/portus-gateway --version 0.4.0 \
  --namespace portus --create-namespace