Redis pipelining removes the round trips, not the work

A hundred Redis commands issued one at a time cost a hundred network round trips. On the same host that is around a millisecond total; across an availability zone it is closer to a hundred, and the server was idle for almost all of it.

$pipe = $redis->multi(Redis::PIPELINE);

foreach ($ids as $id) {
    $pipe->hGetAll("product:{$id}");
}

$results = $pipe->exec();

Pipelining sends the batch without waiting for each reply, so the cost becomes one round trip plus the server-side execution. It is not a transaction — commands are not atomic as a group and a failure part-way through does not roll anything back; MULTI/EXEC is the separate feature for that. Keep batches bounded, because both client and server buffer the whole thing in memory.