Вопрос проверяет знание слабых сторон asyncio, его ограничений и типичных трудностей при построении асинхронных систем.
Главное ограничение asyncio — все корутины выполняются в одном потоке, поэтому любые блокирующие операции «замораживают» весь event loop. CPU-ёмкие задачи также блокируют выполнение других корутин. Асинхронный стек ошибок сложнее читать, а отладка требует специальных инструментов. Не все библиотеки поддерживают async-режим, поэтому приходится использовать thread pool для совместимости. Асинхронный код усложняет архитектуру и требует строгой дисциплины при работе с I/O.
Несмотря на свою производительность для I/O-задач, asyncio имеет ряд ограничений.
Все корутины работают в одном потоке.
Если вы выполните блокирующую операцию:
time.sleep()
тяжелый CPU-цикл
блокирующий запрос к базе
то заморозится весь event loop.
Асинхронность не обходит GIL:
корутина, занимающая CPU, блокирует остальных;
нет реального параллелизма для Python-кода.
Если библиотека не поддерживает async (например, обычный клиент Redis, Postgres, S3):
переход на асинхронную версию может быть невозможен;
приходится использовать обёртки через ThreadPoolExecutor, что снижает эффективность.
трассировки ошибок могут быть запутанными;
исключения могут возникать «асинхронно» в задачах;
нужно отслеживать отменённые задачи и утечки.
Забытый await превращает корутину в незапущенный объект.
Неправильный вызов блокирующей функции ломает всю систему.
Код становится менее линейным, его сложнее читать и объяснять.
Например, Django работает синхронно — полноценный переход на async требует переписывания middleware, ORM и т.п.
Нет — нужно городить thread pool.
Есть — могут быть нестабильны или медленнее.
overhead ожиданий и переключений может быть великим при коротких задачах;
большое число задач может приводить к росту памяти;
планировщик не гарантирует fairness: некоторые задачи могут «голодать».
asyncio отлично справляется с большим количеством I/O-операций, но плохо подходит для CPU-нагрузки, требует строгой дисциплины и зависит от совместимости библиотек. Его нужно применять там, где большинство задач — сетевые запросы, а не вычисления.