Skip to content

Optimize OPA plugin: Replace synchronous requests with async httpx client #1931

@crivetimihai

Description

@crivetimihai

Summary

The OPA (Open Policy Agent) plugin uses synchronous requests.post() which blocks the async event loop during policy evaluation.

Problem

File: plugins/external/opa/opapluginfilter/plugin.py (line 152)

import requests

# Current pattern - blocks async event loop
response = requests.post(opa_url, json=input_data)

When the OPA plugin is enabled and evaluates policies, each policy check blocks the entire async worker until the HTTP request completes. This can cause:

  • Increased latency for all concurrent requests
  • Reduced throughput under load
  • Event loop starvation with slow OPA servers

Proposed Solution

Replace synchronous requests with the shared async httpx client:

from mcpgateway.services.http_client_service import get_http_client

# Async pattern - non-blocking
client = await get_http_client()
response = await client.post(opa_url, json=input_data)

Or if the plugin hook is synchronous, use httpx.Client with connection pooling:

import httpx

# If sync context is required, at minimum use pooled client
# Initialize once in plugin __init__
self._http_client = httpx.Client(
    limits=httpx.Limits(max_connections=100, max_keepalive_connections=20)
)

# Reuse in policy checks
response = self._http_client.post(opa_url, json=input_data)

Impact

  • Performance: Eliminates event loop blocking during OPA policy evaluation
  • Throughput: Allows concurrent request processing while waiting for OPA
  • Consistency: Aligns with async patterns used throughout the gateway

Acceptance Criteria

  • Replace requests.post() with async httpx or pooled sync client
  • Ensure proper client lifecycle management (shutdown cleanup)
  • Add timeout configuration for OPA requests
  • Update plugin tests

References

  • mcpgateway/services/http_client_service.py - Shared async client pattern
  • todo/pooling-optimizations.md - Full optimization analysis

Metadata

Metadata

Labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions