Do I need to specify any params to ensure requests are concurrent?

No additional params are required, but you have to do them all in the same call, just like it’s documented.

Whether the requests will be performed concurrently is entirely dependent on the server, i.e. HTTP/2 enabled servers can receive multiple requests at the same time, and HTTP/1.1 servers supporting pipeline as well.

Concurrency is therefore protocol-dependent, and httpx will not maintain its own thread pool to enable this. If the server you’re requesting to doesn’t fit the criteria above, check Thread Safety.

Will each thread need its own static Session object with the persistent plugin in order to leverage the persistent connections?

No. httpx handles the complexity for you, so you just need to assign HTTPX.plugin(:persistent) to a variable, and this can be used in any context.

httpx does maintain a per-thread connection pool however, meaning that, if you’re using multiple threads, connections to the same origin server will only be shared per-thread.

How can I tell if connections are being reused?

You can troubleshoot that by enabling the logs, where information of DNS requests, TLS handshake and connection state transitions will be displayed.

How do I force HTTP/1.1 even if the server supports HTTP/2?

You must disable ALPN negotiation:

HTTPX.with(ssl: { alpn_protocols: %w[http/1.1]}).get(....

Next: Why?