The Request-Response Trap: Sync vs. Async UX
Standard web servers—whether running Node.js event loops, Python ASGI workers, or Go routines—are engineered for fast I/O where queries resolve in 10ms to 100ms. An LLM completion query, however, routinely requires anywhere from 1,500ms to 12,000ms depending on prompt length, model reasoning depth, and upstream cloud load.
When dozens of concurrent users trigger a synchronous HTTP endpoint at the same time, server worker pools become saturated, reverse proxies (like Cloudflare, Nginx, or AWS ALB) fire 504 Gateway Timeouts, and your core application grinds to a halt.
The primary architectural rule of production AI is establishing a strict boundary between real-time streaming and asynchronous background execution. If a user is actively waiting for generative text in an interactive workflow, stream the tokens immediately over HTTP/2 using Server-Sent Events (SSE). If the task involves document analysis, batch summarization, vector indexing, or multi-step reasoning, it must NEVER run inside the HTTP request loop. Accept the payload, push a job to an asynchronous queue (e.g., Redis via BullMQ or Celery), and return an immediate HTTP 202 Accepted status with a correlation job ID.
- Decouple long-running AI operations (>3s) from HTTP request cycles using Redis, BullMQ, or Celery queues.
- Return HTTP 202 Accepted with a job ID and subscribe the client via WebSockets or polling.
- Enforce strict upstream proxy timeouts (e.g. 15s) with client-side cancellation propagation.
