-
Notifications
You must be signed in to change notification settings - Fork 614
[PERFORMANCE]: Fix N+1 Query in list_tools - Missing joinedload for gateway #1879
Copy link
Copy link
Closed
Copy link
Labels
performancePerformance related itemsPerformance related itemspythonPython / backend development (FastAPI)Python / backend development (FastAPI)
Milestone
Description
Summary
The list_tools() method in tool_service.py triggers N+1 queries when accessing the gateway_slug property. Each tool causes a separate database query to load its gateway relationship.
Root Cause
Location: mcpgateway/services/tool_service.py:1504
The query is built without eager loading:
query = select(DbTool).order_by(desc(DbTool.created_at), desc(DbTool.id))When convert_tool_to_read() accesses gateway_slug (line 536):
tool_dict["gateway_slug"] = getattr(tool, "gateway_slug", "") or ""The gateway_slug hybrid property (db.py:2831) triggers lazy loading:
@hybrid_property
def gateway_slug(self) -> Optional[str]:
return self.gateway.slug if self.gateway else NoneImpact
- With 50 tools: 51 queries instead of 1-2
- At ~5ms per query: ~250ms overhead per request
- At 2000 RPS with 20% hitting /tools: 100+ extra DB queries/second
- Contributes to "idle in transaction" connection buildup
Fix
Add joinedload(DbTool.gateway) to the query:
from sqlalchemy.orm import joinedload
query = select(DbTool).options(joinedload(DbTool.gateway)).order_by(desc(DbTool.created_at), desc(DbTool.id))Reference
list_server_tools() at line 1643 already uses the correct pattern:
select(DbTool).options(joinedload(DbTool.gateway))...Verification
Existing test confirms the issue and fix:
tests/performance/test_db_query_patterns.py:68-test_list_tools_with_gateway_n1_potentialtests/performance/test_db_query_patterns.py:91-test_list_tools_with_eager_loading
Acceptance Criteria
- Add
joinedload(DbTool.gateway)tolist_tools()query - Audit similar patterns in
list_resources,list_prompts,list_servers - Verify with load test (
make load-test-ui) - Passes
make verify
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
performancePerformance related itemsPerformance related itemspythonPython / backend development (FastAPI)Python / backend development (FastAPI)