performance

  • A read replica, and the six queries that could not use it

    A primary at 80% CPU and reports running during the working day. Setting up the replica takes an afternoon; the consistency model takes a month.

  • HTTP/3 at the edge, and nothing behind it

    Enabling QUIC on the edge terminator changes the client leg and nothing else, which is worth being clear about before reading a benchmark. Thirty milliseconds on the p75…

  • –mount=type=cache for composer, measured

    The layer cache handles an unchanged lock file; a cache mount handles the case where the lock file changed and 90% of the packages did not. Measured over…

  • A transition that made a filter feel instant

    A filter input rendering 4,000 rows on every keystroke, where the typing lag was the rendering rather than the filtering. The input updates immediately and the list update…

  • Load testing one endpoint before a launch

    A full load test of a system is a project; a load test of the one endpoint a campaign will hit is an afternoon. The mismatch between the…

  • The Dockerfile that finally stopped installing the world

    A 1.4 GB image and a six-minute build, for an application that is 40 MB of PHP. Most of it is build tooling that shipped by accident.

  • The __destruct that ran after the response was sent

    A profiler showed 140 ms of work happening after the response had been flushed, which is invisible to the user and entirely visible in the worker’s throughput. Destructor-based…

  • The REST response we cached at the edge

    A public REST endpoint serving the same payload to everybody, hit forty thousand times a day, and generated forty thousand times. WordPress sends no-cache on REST responses by…

  • Gzip against brotli on an API response, measured

    Brotli compresses better and costs more CPU, and whether that is worth it depends on a number nobody measures. The high compression levels are for static assets compressed…

  • WeakMap for a cache that must not keep objects alive

    A per-request memoisation cache keyed by object was holding every entity loaded during a long-running command, and the command was using 900 MB by the end. This only…