What is the proper design pattern for plugins that must submit multiple requests to Elasticsearch?

You generally write your own ActionListener<...> and pass it to the .execute(listener) method rather than calling .get(). Your listener's onResponse() method can then run the next step of the process.

There's a bunch of utilities to make this a bit simpler and/or to encapsulate common patterns, e.g. ActionListener#delegateFailure, ActionListener#map, RestResponseListener<>, StepListener<>, ActionRunnable<> etc. It always ends up with things in a slightly funny order, but there's not really a way around that. Native syntax for async code would be nice, but that's not something Java has today.