One virtual thread per session

Every active session runs on its own virtual thread. Virtual threads are cheap (thousands per JVM) and yield automatically on blocking I/O. This is why you can have 10,000 concurrent sessions on a single instance.

Advertisement

Blocking is fine in tools

You don't need CompletableFuture or reactive libraries. Just call the API synchronously:

public Object call(Map args) {
  return httpClient.send(  // blocking
    request,
    HttpResponse.BodyHandlers.ofString()
  );
}
Advertisement

What to avoid

Synchronized blocks and Object.wait() pin virtual threads to their carrier, defeating the whole model. Use ReentrantLock or higher-level concurrency utilities instead.