The fastest request never reaches PHP

One header, and the FPM load graph fell off a cliff. Cache-Control: public, s-maxage=60 A public catalog page on one project renders the same HTML for every anonymous visitor. Same queries, same JSON from the search service, same template, thousands of times per hour. We profiled it, we tuned it, and only then asked the obvious question: why is PHP involved in the second request at all. HTTP had the answer before my career started. public says a shared cache may store the response. s-maxage gives the CDN or reverse proxy its own lifetime, separate from browser max-age. With Varnish in front, the request path splits in two. MISS: full stack, FPM, database, sixty milliseconds. HIT: the proxy answers from memory, the PHP process never starts, the database never hears about it. Nothing in the application got faster. There was simply less application running. ...

December 3, 2024 · 2 min · Murat Useinov

Waiting for three APIs, one at a time

Three external calls on one page: prices, stock, delivery estimate. Each answers in about 300 ms. The page waits a full second, because we call them one after another. PHP is synchronous, what can you do. Turns out, something. Symfony HttpClient is lazy. request() sends and returns immediately. The waiting happens when you read the response. So start all three, read later: $prices = $client->request('GET', $pricesUrl); $stock = $client->request('GET', $stockUrl); $delivery = $client->request('GET', $deliveryUrl); $data = [ 'prices' => $prices->toArray(), 'stock' => $stock->toArray(), 'delivery' => $delivery->toArray(), ]; Under the hood it is curl multi. Three requests fly at once, wall time is the slowest one instead of the sum. Our second became 350 ms. No swoole, no reactphp, no async rewrite. Same boring controller. ...

April 21, 2020 · 2 min · Murat Useinov