В FastAPI клиентский дисконнект по умолчанию не останавливает выполнение обработчика, поэтому стриминг от большой языковой модели (LLM) может продолжаться «в пустоту». Главный итог: отключение нужно учитывать явно, иначе страдают ресурсы и корректность работы с БД.По умолчанию разрыв соединения не прерывает пользовательский код: для обычных эндпоинтов событие http.disconnect игнорируется.Для стриминга (StreamingResponse, EventSourceResponse) отключение ловится, но отмена может прервать транзакцию или код очистки.В одном кейсе транзакции оставались открытыми до 40 минут (idle in transaction), после чего появились алерты о «мёртвых» соединениях в пуле.Пример с нестриминговым эндпоинтом: были согласованы лимит параллельности 32 запроса и таймаут 30 секунд, но из-за бага у клиента таймаут стал 10 секунд и начались повторы.В примерах используются версии: Uvicorn 0.40.0, Starlette 0.50.0, FastAPI 0.128.0, vLLM v0.13.0.Нюанс ASGI: требование бросать OSError при send() появилось в ASGI 2.4, а Uvicorn 0.40.0 реализует 2.3 и при disconnected просто отбрасывает данные.Почему это важно: В сервисах со стримингом ответов от LLM дисконнект клиента может привести к тому, что GPU продолжит генерировать токены, занимая ресурсы self-hosted моделей или накапливая расходы у внешних провайдеров. Ещё заметнее риск для базы данных: транзакции могут остаться незавершёнными, а в пул возвращаются соединения в невалидном состоянии. Без явной обработки теряется статистика незавершённых запросов, что мешает отладке и аналитике.На что обратить внимание: В статье подчёркивается, что 100% гарантии обнаружения дисконнекта в рамках одного HTTP-запроса недостижимы, поэтому важен баланс между корректностью критичных фаз и возможностью прерывать долгие. Для нестриминговых ответов признак отключения появляется только при явном опросе request.receive() и проверке http.disconnect; метод Request.is_disconnected() описан как ненадёжный при BaseHTTPMiddleware. В стриминге ключевой сигнал — CancelledError, а риск связан с двумя конкурирующими путями завершения (например, ручной break плюс отмена таски фреймворком), из-за чего может пропускаться логика очистки.