You don't show you code, so I can't tell exactly what you have done. I suspect, however, that your async version behaves like the sync version, that is, the client does not start then next AMI invocation until the result of the previous AMI invocation has arrived. If you do this, you definitely will not see much of a difference in performance because, in effect, your code simply emulates the behavior of synchronous invocations. However, you will see a difference if you allow the client to have more than one outstanding AMI call. This can provide increased overall throughput because it keeps the TCP "pipe full", that is, the client can do I/O in one thread while another thread is using the CPU to process data. (IcePatch2 uses this technique to get high throughput for file transfers.)