Skip to content

Granian Server

Granian is a high-performance Rust HTTP server for Python applications. It supports ASGI, WSGI, and RSGI interfaces with HTTP/1.1 and HTTP/2 protocols.

Why Granian?

  • Performance: ~50,000 req/s vs Uvicorn's ~45,000 req/s in benchmarks
  • Memory: ~15MB base footprint per worker
  • HTTP/2: Native h2c (HTTP/2 cleartext) support
  • Rust: Memory-safe, no GIL contention in the server layer

Installation

pip install granian

Command Line Usage

ASGI (FastAPI)

# Basic
granian --interface asgi myapp.main:app

# With workers and HTTP/2
granian --interface asgi --workers 4 --http 2 myapp.main:app

# Full configuration
granian --interface asgi \
    --host 0.0.0.0 \
    --port 8000 \
    --workers 4 \
    --runtime-threads 2 \
    --http 2 \
    --loop uvloop \
    myapp.main:app

WSGI (Django)

# Basic
granian --interface wsgi myapp.wsgi:application

# With workers and HTTP/2
granian --interface wsgi --workers 4 --http 2 myapp.wsgi:application

Programmatic Usage

ASGI Configuration

"""Granian ASGI server configuration example.

Shows how to run FastAPI applications with Granian.
"""

from granian import Granian
from granian.constants import HTTPModes, Interfaces, Loops

# Basic ASGI configuration
server = Granian(
    target="myapp.main:app",
    address="0.0.0.0",
    port=8000,
    interface=Interfaces.ASGI,
    workers=4,
)

# With HTTP/2 support (h2c - HTTP/2 cleartext)
server_h2 = Granian(
    target="myapp.main:app",
    address="0.0.0.0",
    port=8000,
    interface=Interfaces.ASGI,
    workers=4,
    runtime_threads=2,
    http=HTTPModes.http2,  # Enable HTTP/2
    loop=Loops.uvloop,  # Use uvloop for better performance
)

# Start the server
# server.serve()

WSGI Configuration

"""Granian WSGI server configuration example.

Shows how to run Django applications with Granian.
"""

from granian import Granian
from granian.constants import HTTPModes, Interfaces

# Basic WSGI configuration for Django
server = Granian(
    target="myapp.wsgi:application",
    address="0.0.0.0",
    port=8000,
    interface=Interfaces.WSGI,
    workers=4,
)

# With HTTP/2 support
server_h2 = Granian(
    target="myapp.wsgi:application",
    address="0.0.0.0",
    port=8000,
    interface=Interfaces.WSGI,
    workers=4,
    blocking_threads=2,
    http=HTTPModes.http2,
)

# Start the server
# server.serve()

HTTP/2 and h2c

Granian supports HTTP/2 over cleartext (h2c) which is useful for internal services behind a load balancer that terminates TLS.

HTTP Modes

Mode Value Description
Auto auto Automatic detection (default)
HTTP/1.1 1 Force HTTP/1.1 only
HTTP/2 2 Force HTTP/2 (h2c)

h2c Client Testing

# HTTP/2 with prior knowledge (direct h2c)
curl --http2-prior-knowledge http://localhost:8000/

# HTTP/1.1 to HTTP/2 upgrade (may not work with all servers)
curl --http2 http://localhost:8000/

h2c Upgrade Limitation

The HTTP/1.1 to HTTP/2 upgrade mechanism (curl --http2) may not work with Granian. Use --http2-prior-knowledge for direct HTTP/2 connections, or use HTTPS where ALPN handles protocol negotiation.

Configuration Options

Option CLI Flag Default Description
Interface --interface rsgi asgi, wsgi, or rsgi
Host --host 127.0.0.1 Bind address
Port --port 8000 Bind port
Workers --workers 1 Number of worker processes
Runtime Threads --runtime-threads 1 Async runtime threads (ASGI)
Blocking Threads --blocking-threads auto Threads for blocking ops (WSGI)
HTTP --http auto HTTP version: auto, 1, 2
Loop --loop auto Event loop: auto, asyncio, uvloop
Backlog --backlog 1024 Socket backlog size
Backpressure --backpressure - Max concurrent requests per worker

Production Recommendations

Worker Count

# CPU-bound: match CPU cores
granian --workers $(nproc) --interface asgi myapp.main:app

# I/O-bound: 2-4x CPU cores
granian --workers $(($(nproc) * 2)) --interface asgi myapp.main:app

With Application Kit

For FastAPI applications using Application Kit:

# Development
DEVELOPMENT=yes granian --interface asgi \
    --workers 1 \
    --reload \
    myapp.main:app

# Production with HTTP/2
granian --interface asgi \
    --workers 4 \
    --runtime-threads 2 \
    --http 2 \
    --backpressure 256 \
    myapp.main:app

See Also