<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Packaging on MongrelDB</title><link>https://www.mongreldb.com/articles/tags/packaging/</link><description>Recent content in Packaging on MongrelDB</description><image><title>MongrelDB</title><url>https://www.mongreldb.com/assets/og-mongreldb.png</url><link>https://www.mongreldb.com/assets/og-mongreldb.png</link></image><generator>Hugo</generator><language>en-US</language><lastBuildDate>Mon, 28 Sep 2026 06:00:00 -0500</lastBuildDate><atom:link href="https://www.mongreldb.com/articles/tags/packaging/index.xml" rel="self" type="application/rss+xml"/><item><title>Pure PHP in 2026: A Database Client That Ships with Composer</title><link>https://www.mongreldb.com/articles/2026/09/pure-php-in-2026-a-database-client-that-ships-with-composer/</link><pubDate>Mon, 28 Sep 2026 06:00:00 -0500</pubDate><guid>https://www.mongreldb.com/articles/2026/09/pure-php-in-2026-a-database-client-that-ships-with-composer/</guid><description>Installing a database driver in PHP used to mean phpize, a compiler, and a prayer; the MongrelDB PHP client is pure PHP installed with one Composer command, and this post explains why that is still a feature in 2026.</description><content:encoded><![CDATA[<p>Ask anyone who maintained PHP infrastructure between 2004 and 2015 what installing a database driver involved and the honest answer is a compiler, because the driver was C code that had to be built against the exact internals of the PHP you were running, and every link in that chain had its own way of failing on a Friday afternoon. <code>phpize</code> needed the development headers your distro kept in a separate package, the build needed a PHP API number that bumped whenever upstream touched the internals, the resulting <code>.so</code> had to match your thread-safety flavor and your architecture, and then a routine upgrade of PHP from one minor version to the next silently invalidated the whole thing, so the first request after patch night was a white page and a log full of &ldquo;Unable to load dynamic library.&rdquo; The interesting question in 2026 is not whether that pain still exists but whether avoiding it is still worth designing around, and our answer when we built the MongrelDB PHP client was yes without qualification, which is why the entire client is plain PHP that installs with one Composer command and never touches a compiler anywhere in the loop.</p>
<h2 id="what-one-composer-command-actually-buys">What one Composer command actually buys</h2>
<p><code>composer require visorcraft/mongreldb-php</code> pulls a package whose entire production dependency list fits on one screen:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#e6db74">&#34;require&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;php&#34;</span>: <span style="color:#e6db74">&#34;&gt;=8.4&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ext-curl&#34;</span>: <span style="color:#e6db74">&#34;*&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;ext-json&#34;</span>: <span style="color:#e6db74">&#34;*&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Read that list the way an ops person reads it, because ext-json has been compiled into PHP 8 since day one and cannot be disabled, which makes it a dependency in name only, and ext-curl ships in the PHP source tree and comes enabled in every standard distribution build we have ever checked, so on a standard PHP 8.4 or 8.5 build from any major distribution the real requirement reduces to &ldquo;PHP exists,&rdquo; and the worst case on a minimal install is one distro package like <code>php-curl</code>, not a compile step. Just as important is what is not there: no third-party packages underneath, a dependency tree with depth one, nothing transitive for <code>composer update</code> to surprise you with at 2 AM, and a supply chain audit that means reading one repository instead of forty.</p>
<h2 id="why-the-abi-treadmill-still-matters">Why the ABI treadmill still matters</h2>
<p>The extension ecosystem has not gotten calmer with age, since every PHP minor release bumps the internal API and every native extension has to be rebuilt against it, which is why Xdebug publishes a new build per PHP version and why smaller PECL packages routinely lag a fresh PHP release by weeks or months, leaving teams that depend on a native database driver unable to upgrade PHP when they want to and only able to upgrade when their driver&rsquo;s maintainer gets around to it. Docker makes the cost quieter but not smaller: the moment a Dockerfile contains <code>pecl install</code> or <code>docker-php-ext-install</code>, the image build needs a compiler toolchain and the <code>-dev</code> headers, the image either grows by hundreds of megabytes or you learn multi-stage builds the hard way, and every CI run pays for a compile that has nothing to do with your application code. A pure PHP client collapses all of that into the same <code>composer install</code> the rest of your dependencies already use, against a base image that never needed gcc, with a <code>composer.lock</code> that makes the whole thing reproducible and rollback a one-line revert.</p>
<h2 id="where-the-speed-actually-comes-from">Where the speed actually comes from</h2>
<p>The honest objection to a pure PHP database client is that PHP code runs slower than C code, which is true as far as it goes but misidentifies where the time actually goes in a client-server conversation. This client&rsquo;s job is to serialize a request, send it to <code>mongreldb-server</code> over a keep-alive HTTP connection, and decode the JSON that comes back, while the heavy lifting, meaning index traversal, vector search, constraint checks, and the WAL fsync, happens in Rust on the other side of the socket, so the PHP-side cost per call is microseconds of <code>json_encode</code> wrapped around milliseconds of work the engine was going to do anyway. Within a single request the cURL transport pools keep-alive connections on its own, and on PHP 8.5 you can opt into persistent cURL sharing so DNS results, TLS sessions, and where libcurl allows it the connection cache itself survive across FPM requests, which is exactly the kind of runtime feature a pure PHP client can adopt the day it ships, because adopting it means a <code>function_exists('curl_share_init_persistent')</code> check and a function call, not waiting for an extension maintainer to cut a release.</p>
<p>Could we have shaved the serialization cost with FFI, which has shipped since PHP 7.4 and could call <code>libmongreldb.so</code> directly in process? Probably, and we chose not to, because FFI drags back precisely what we set out to remove: a native artifact that must exist on every host at a path everyone agrees on, built for the right platform, plus an <code>ffi.enable</code> setting that hardened setups and most shared hosts leave off. HTTP costs a round trip and a JSON pass that we can measure, and it buys a client that runs anywhere PHP runs with zero install ceremony, a trade that reads better every year rather than worse.</p>
<h2 id="the-modern-equivalent-of-the-old-convenience">The modern equivalent of the old convenience</h2>
<p>We accepted the compile step for years because there was no alternative, since the old <code>mysql</code> extension lived inside the PHP source tree itself and you got your driver by building PHP, which felt like convenience only because nobody had shown us anything better. The modern equivalent of that convenience is not a better extension but no extension at all: a client that arrives through the same tool managing the rest of your dependencies, upgrades atomically with your application, and never turns a PHP minor release into a two-ticket sprint waiting on someone else&rsquo;s build farm. Twenty years ago the best database driver was the one already compiled into your PHP; in 2026 the best one is the one that never needed compiling, and everything else in this series, the idempotent transactions, the index-aware query builder, the status-code-shaped exceptions, stands on top of that one decision.</p>
]]></content:encoded></item></channel></rss>