Skip to content

ADR-0024: Adopt uvicorn[standard] for Enhanced Server PerformanceΒΆ

  • Status: Accepted
  • Date: 2025-12-21
  • Deciders: Core Engineering Team

ContextΒΆ

MCP Gateway uses Gunicorn with Uvicorn workers (uvicorn.workers.UvicornWorker) as its production ASGI server stack. The base uvicorn package provides functional async HTTP serving, but lacks optional performance-enhancing components that can provide 15-30% throughput improvements with zero code changes.

The uvicorn package offers a [standard] extras bundle that includes: - uvloop: A Cython/libuv-based event loop (2-4x faster than asyncio on Linux/macOS) - httptools: A C extension for HTTP parsing (based on Node.js http-parser) - websockets: WebSocket protocol implementation - watchfiles: Efficient file watching for development --reload

Without these extras, Uvicorn falls back to: - Python's standard asyncio event loop - Python's pure-Python HTTP parser - Basic file watching mechanisms

DecisionΒΆ

We will adopt uvicorn[standard] as the default uvicorn installation to enable high-performance server components automatically.

Change:

# pyproject.toml
-    "uvicorn>=0.38.0",
+    "uvicorn[standard]>=0.38.0",

Components included:

Package Purpose Platform Support
uvloop Fast event loop (libuv-based) Linux, macOS only
httptools Fast HTTP parsing (C extension) All platforms
websockets WebSocket support All platforms
watchfiles Fast file watching for –reload All platforms

How it works: - When Gunicorn spawns UvicornWorker processes, Uvicorn automatically detects and uses these high-performance components - No configuration changes required - detection is automatic - On Windows, uvloop gracefully skips (unavailable), but httptools still provides benefits

ConsequencesΒΆ

PositiveΒΆ

  • 15-30% higher throughput - Faster event loop and HTTP parsing reduce per-request overhead
  • Lower latency - uvloop provides 20-40% lower event loop latency
  • Zero code changes - Drop-in enhancement, automatically detected by Uvicorn
  • Consistency - Matches other projects in the repository (langchain_agent, mcp_eval_server)
  • Better development experience - watchfiles provides faster, more reliable --reload
  • Production-ready - Used by major deployments (Microsoft, Mozilla, Sentry)

NegativeΒΆ

  • Platform-specific behavior - uvloop unavailable on Windows (graceful fallback)
  • Binary dependencies - Requires compilation or prebuilt wheels (available for all major platforms)
  • Slightly larger install - Additional packages (~5MB)

NeutralΒΆ

  • No configuration needed - Uvicorn auto-detects available components
  • Transparent to application - FastAPI/Starlette code unchanged

Performance ImpactΒΆ

Based on uvloop and httptools benchmarks:

Metric Base Uvicorn With [standard] Improvement
Event loop latency Baseline -20-40% uvloop
HTTP parsing overhead Baseline -40-60% httptools
Requests/second Baseline +15-30% Combined
--reload responsiveness Baseline Faster watchfiles

Real-world impact: - Simple JSON endpoints: 15-25% faster - WebSocket connections: Better handling via optimized websockets library - Development cycle: Faster file change detection with watchfiles - Memory: Similar (slight increase for additional packages)

Alternatives ConsideredΒΆ

Option Why Not
Base uvicorn only Leaves 15-30% performance on the table
Manual installation of extras Error-prone, inconsistent across environments
Granian (Rust HTTP server) Larger migration, under evaluation (see #1695)
Hypercorn Less community adoption, similar feature set

Relationship to Granian MigrationΒΆ

This change is complementary to the potential Granian migration (#1695): - uvicorn[standard]: Low-effort optimization (this ADR) - implement now - Granian: Larger migration to Rust-based server - evaluate separately

If Granian is adopted in the future, this change would be superseded. Until then, uvicorn[standard] provides immediate benefits with minimal risk.

Migration PathΒΆ

  1. Update pyproject.toml: uvicorn[standard]>=0.38.0
  2. Reinstall dependencies: uv sync or pip install -e .
  3. Verify extras installed: pip list | grep -E "uvloop|httptools"
  4. Run test suite: make test
  5. Benchmark (optional): Compare RPS before/after

VerificationΒΆ

# Check installed packages
uv pip list | grep -E "uvicorn|uvloop|httptools|websockets|watchfiles"

# Expected output (Linux/macOS):
# httptools    0.6.x
# uvicorn      0.38.0
# uvloop       0.21.x
# watchfiles   1.x.x
# websockets   15.x.x

# On Windows, uvloop will be absent (expected)

StatusΒΆ

This decision has been implemented. The pyproject.toml now specifies uvicorn[standard]>=0.38.0.

ReferencesΒΆ