интересные вопросы задаёте, пока нет быстрого ответа. (Я не использую userver в повседневной жизни, так как мой проект - симулятор немного о другом). Насколько я понимаю в специфических сценариях типа postgress драйвера используется нижележащий threadpool.
Кажется (кажется) что таки и в общем режиме сопрограммы запускаются на фиксированном пуле boost::coroutines2::coroutine (не уверен, что разница тут большая).
Если просто:
1. В случае когда мы одновременно работаем с тысячами/десятками тысяч одновременных соединений, мы регистрируем все сокеты в реакторе(epoll, если речь про Linux) и реакцию на события сети получаем через колбеки. Естественно нам в данном случае нет смысла задумываться о синхронизации доступа к разделяемым данным, если речь идёт о колбеках, вызываемых в контекте того потока, где выполняется epoll. В них вызовы всех обработчиков сериализованы.
2. Почему бы данное свойство(отсутствие необходимости использовать примитивы синхронизации) не использовать при работе с лёгкими потоками? На каждое соединение запускаем лёгкий поток, но так, чтобы он был привязан к конкретному физическому потоку OS. Но в отличие от п.1, у нас нет лапши колбеков с невнятным потоком управления и stack ripping'ом
Если нужно решить вопрос балансировки, перешедуливаем сопрограммы на другой тред OS