On Windows you may consider using higher level IO routines. For example, for HTTP requests you can use WinHTTP which is super fast and scalable. For other IOs you can use Windows Thread Pool API(https://learn.microsoft.com/en-us/windows/win32/procthread/t...) so that you do not need to manually manage threads or register/unregister IO handlers/callbacks. gRPC uses that.
Though Windows IOs internally are all async, actually it makes using sync I/O easier and you do not need to say it is a super bad idea. Windows has IOCP. If the machine has n logical CPUs, you may create a thread pool with 2*n threads. And, by default the operating system will not make more than n threads active at the same time. When one of the threads is doing blocking IO and entered IO wait state, the OS will wake-up another thread and let it go. This is why the number of threads in the thread pool needs be larger than than the number of CPUs. This design doesn't lead to an optimal solution, however, practically it works very well. In this setting you still have the flexibility to use async IOs, but it is not a sin to use sync IO in a blocking manner in a thread pool.
Disclaimer: I work at Microsoft and ship code to Windows, but the above are just my personal opinions.
Disclaimer: I work at Microsoft and ship code to Windows, but the above are just my personal opinions.