Почему Uvicorn советуют запускать через gunicorn?
Потому что uvicorn - это не менеджер процессов. Он запускает ровно один процесс, в котором будет один ивент луп, который будет всё крутить на одном ядре. Если у тебя 4ядерный проц на сервере, то для полной утилизации ресурсов нужно запустить как минимум 4 таких uvicorn’ов. Для этого gunicorn здесь и нужен.
Uvicorn работает в несколько потоков ( config.workers )
server = Server(Config)
if server.config.workers > 1:
  app = Multiprocess(server.config, target=server.run, sockets=[server.config.bind_socket()]).run
else:
  app = server.run

app()