I believe NIOAsyncChannel upholds backpressure correctly (@FranzBusch will have the details). So it's not pushing new connections onto the Swift Concurrency pools, it's pulling channels from Concurrency land. This pulling will only happen if the Concurrency threads aren't already overloaded. Of course there might be scenarios where some details change but by and large it should be fine.
For peak performance you'll want to get rid of the extra latency for the thread switches between Concurrency and I/O and that can be done by installing NIO as your Concurrency executor which means async functions run on NIO's EventLoops.
Truthfully though, I'd be shocked if there are many higher-level server applications that don't have a hidden unbounded queue hidden somewhere. A lot of file system/database calling frameworks have unbounded queues where work can just pile up without a limit... But these can be fixed if necessary.
And this is why IMHO a low-level thing like SwiftNIO must be held to a somewhat higher standard here: It is important it doesn't impose any unbounded queues that a user can't fix. The 'no unbounded queues' guarantee is upheld even with NIOAsyncChannel, you are still in control if and when connections/requests are accepted. And of course NIO's core sits 'in front' of NIOAsyncChannel so if you already have some custom circuit breaking/backpressuring logic you can continue adding that to the serverChannelInitializer to slow down connection acceptance to the rate/count you want. And by adding handlers to the childChannelInitializer you can control the number of inflight requests. Both allow you to slow things down by slowing down (or outright stopping) outbound read events.
But in most cases I'd think just using NIOAsyncChannel should be fine because it pulls new connections/requests. So if you're overloaded it'll naturally pull more slowly
. Internally it will uphold the backpressure also by slowing the read events just like anything else would, it doesn't have any privileged access.