uvicorn icon indicating copy to clipboard operation
uvicorn copied to clipboard

Server hangs completely on JSON POST requests above certain size threshold with async SQLAlchemy dependencies

Open sammcvicker opened this issue 2 months ago • 0 comments

Description

Server completely hangs when receiving JSON POST requests above a certain size threshold (around 15 line items in our case, ~171 bytes). Requests never reach FastAPI middleware or application code - they hang at the Uvicorn/ASGI layer.

Environment

  • Uvicorn version: (need to check, running via uvicorn.run())
  • Python version: 3.10+
  • OS: macOS Darwin 24.6.0
  • FastAPI version: Latest
  • Database: SQLAlchemy async with SQLite + NullPool
  • Installation method: uv package manager

Steps to Reproduce

  1. Create async FastAPI endpoint with async SQLAlchemy session dependency:
from fastapi import FastAPI, Depends
from sqlalchemy.ext.asyncio import AsyncSession

@app.post("/api/generate/documents")
async def generate_documents(
    request: GenerateDocumentsRequest,
    session: AsyncSession = Depends(get_database_session)
):
    # ... route handler code
  1. Add middleware logging to track requests:
@app.middleware("http")
async def log_requests(request: Request, call_next):
    print(f"[MIDDLEWARE] Incoming request: {request.method} {request.url.path}")
    response = await call_next(request)
    return response
  1. Send JSON POST requests with increasing payload sizes:
# Works: 10 line items (~130 bytes)
curl -X POST 'http://localhost:8000/api/generate/documents' \
  -H 'Content-Type: application/json' \
  -d '{"num_line_items": 10, "vendor_name": "Test", "buyer_name": "Test", "tax_rate": 0.085, "include_notes": true, "discrepancies": []}'

# Hangs forever: 15+ line items (~171 bytes)
curl -X POST 'http://localhost:8000/api/generate/documents' \
  -H 'Content-Type: application/json' \
  -d '{"num_line_items": 15, "vendor_name": "Test", "buyer_name": "Test", "tax_rate": 0.085, "include_notes": true, "discrepancies": []}'

Observed Behavior

Working requests (≤10 items):

  • Middleware logs appear immediately
  • Request processed in ~0.35s
  • Response returned successfully
  • Server remains responsive

Hanging requests (≥15 items):

  • NO middleware logs (request never reaches FastAPI)
  • Request times out after 60s
  • NO Uvicorn logs at all
  • Server completely hangs - even health check endpoints timeout
  • Server must be killed and restarted

Expected Behavior

All valid JSON POST requests should reach the application layer, regardless of payload size (within reasonable limits).

Diagnostic Details

  1. Request never reaches FastAPI: Middleware logging confirms requests ≥15 items never trigger our middleware
  2. Not application code: Thread pool executors for CPU-intensive work don't help (issue is before our code runs)
  3. Not database: NullPool configuration prevents connection exhaustion
  4. Not request size: Payload is tiny (~171 bytes for 15 items)
  5. Reproducible threshold: Consistently fails at exactly 15 items, works perfectly at 10 items

Uvicorn Configuration

uvicorn.run(
    "main:app",
    host="0.0.0.0",
    port=8000,
    reload=True,
    log_level="info"
)

Workaround

Limiting requests to ≤10 line items prevents the hang, but this appears to be a Uvicorn bug with async request body handling.

Additional Context

  • Issue does NOT occur with smaller payloads
  • Server becomes completely unresponsive after hang (not just slow)
  • No errors logged anywhere (Uvicorn, Python, or application)
  • Issue persists across server restarts
  • Same behavior with curl and browser-based requests

sammcvicker avatar Oct 20 '25 14:10 sammcvicker