« Back
Written by Nuno Maduro on July 15, 2022

Speed Up Your PHP HTTP Guzzle Requests With Concurrency

When building Web applications, it’s very common to make HTTP requests from your backend code to query external APIs. And, when working with PHP, Guzzle is the standard library for making this sort of operations.

Working with Guzzle is simple, it starts by first configuring an $client instance:

use GuzzleHttp\Client;

$client = new GuzzleHttp\Client([
    'base_uri' => 'https://my-target-api.com'
]);

And finally, perform HTTP requests, querying / or making the operations we need:

$response = $client->get('/posts');
$posts = json_decode($response->getBody()->getContents(), true);

$response = $client->get('/comments');
$comments = json_decode($response->getBody()->getContents(), true);

Now, a common mistake when needing to make multiple HTTP requests at the same time is making them sequentially and waiting for every response before issuing the following request, which can cause an N+1 problem:

// Perform and wait for request 1...
// Perform and wait for request 2...
// Perform and wait for request X...
// Total: X * duration of request

To address this issue, and ensure our code scale well no matter the number of requests performed, you can concurrent requests.

With concurrency we can batch all requests, and execute them “at the same time”, meaning that the total amount of time equals the duration of the slowest request:

// Perform request 1...
// Perform request 2...
// Perform request X...
// Wait for all requests...
// Total: Duration of slowest request

And, adjusts the code snippet above making it concurrent, is a simple as using Guzzle’s concurrent API:

$promises = [
    $client->getAsync('/posts'),
    $client->getAsync('/comments'),
];

$responses = GuzzleHttp\Promise\Utils::settle(
    GuzzleHttp\Promise\Utils::unwrap($promises),
)->wait();

$posts = json_decode($responses[0]['value']->getBody()->getContents(), true);
$comments = json_decode($responses[1]['value']->getBody()->getContents(), true);

Keep in mind that the code snippets above assume an HTTP Response Code of 200 in all responses. Therefore, you may need to double-check the HTTP Response Code before actually getting the Response Body Content.

Also, be sure to check Guzzle’s documentation about this topic if you plan to update your code based on information about this article.


I hope you have enjoyed this article. If yes, please consider supporting my work — my mission is to spend more time maintaining the dozens of projects that I've written/collaborated on over the years and continue developing new projects to make PHP development more productive and enjoyable.

github.com/sponsors/nunomaduro