<?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>Shared-Hosting on MongrelDB</title><link>https://www.mongreldb.com/articles/tags/shared-hosting/</link><description>Recent content in Shared-Hosting 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, 14 Sep 2026 09:00:00 -0500</lastBuildDate><atom:link href="https://www.mongreldb.com/articles/tags/shared-hosting/index.xml" rel="self" type="application/rss+xml"/><item><title>Shared Hosting Is Back (Sort Of): Why Pure PHP Databases Matter</title><link>https://www.mongreldb.com/articles/2026/09/shared-hosting-is-back-sort-of-why-pure-php-databases-matter/</link><pubDate>Mon, 14 Sep 2026 09:00:00 -0500</pubDate><guid>https://www.mongreldb.com/articles/2026/09/shared-hosting-is-back-sort-of-why-pure-php-databases-matter/</guid><description>A huge share of the web still runs on hosting plans where you cannot compile anything, and a database client that ships as plain Composer files is the difference between deploying there and telling the customer to move.</description><content:encoded><![CDATA[<p>The number that decides where your software can run is not your infrastructure bill, it is the extension list on a hosting plan that costs less per month than the meeting where you discussed it, and the reason this still matters in 2026 is that a genuinely enormous share of the web lives on exactly those plans, maintained by people who will never open a root shell for you and should not have to.</p>
<h2 id="the-web-did-not-actually-leave">The web did not actually leave</h2>
<p>W3Techs has PHP at roughly seven in ten of the websites whose server-side language can be identified, and WordPress alone sits at around 43 percent of the entire web, with WooCommerce, PrestaShop, and a long tail of agency-built Laravel and Symfony sites stacked on top of that. A meaningful slice of those sites run on shared or cPanel-style managed plans, because for a bakery, a regional law firm, or a two-hundred-client freelance agency, the five-dollar plan is not a compromise, it is the correct amount of hosting, and any software that cannot run there simply does not exist for those buyers.</p>
<p>The industry spent a decade pretending this constraint was gone, since the VPS and container era let developers choose their own runtime and the shared host became something we joked about, but the customers never moved, they just became somebody else&rsquo;s support ticket.</p>
<h2 id="what-the-plan-actually-forbids">What the plan actually forbids</h2>
<p>A shared host gives you PHP-FPM with a fixed, curated extension list, and the list is the whole story: there is no root, there is no <code>phpize</code>, there is no <code>pecl install</code>, and the best-case escape hatch is a cPanel checkbox grid of prebuilt extensions the host compiled once and will patch on their schedule, not yours. The moment your stack depends on a C extension that is not on that grid, and <code>ext-mongodb</code> is the classic example, the support conversation ends in a shrug or in an upsell to a VPS, and the customer hears &ldquo;your software needs different hosting&rdquo; as &ldquo;your software costs more than you said it would.&rdquo;</p>
<p>This is not a new problem wearing a new coat; in 2005 it was the entire industry, every PHP app assumed MySQL over localhost because that is what the plan provided, and the dependency tree of the average app was <code>mysql_*</code> plus whatever GD did. We modernized the runtime and forgot that the constraint moved rather than disappeared, from &ldquo;the host must have MySQL&rdquo; to &ldquo;the host must let you compile,&rdquo; which for a cPanel customer is the same wall painted a different color.</p>
<h2 id="what-pure-php-actually-ships-as">What pure PHP actually ships as</h2>
<p>The mongreldb-php client declares three requirements in <code>composer.json</code>, and two of them are not really requirements at all:</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><code>ext-json</code> has been compiled into PHP itself since 8.0 and cannot be disabled, and <code>ext-curl</code> ships enabled in every cPanel and shared-host image we have ever met, though honesty demands one caveat: it is the single genuine declared dependency of the package, so a hand-rolled minimal container or the official bare <code>php</code> Docker image may need its <code>php-curl</code> equivalent installed first, while the shared hosts this article is about ship it by default. There is no <code>.so</code> to match against the host&rsquo;s PHP build, no ABI that snaps when the host bumps 8.4 to 8.5 over a weekend, and no compile step that a support agent has to bless.</p>
<p>Installation is the boring kind of magic:</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-bash" data-lang="bash"><span style="display:flex;"><span>composer require visorcraft/mongreldb-php
</span></span></code></pre></div><p>What lands in <code>vendor/</code> is plain PHP files with a PSR-4 autoloader, which means deployment is an upload; if the plan gives you SSH, Composer runs on the host, and if it does not, you build <code>vendor/</code> locally and rsync or FTP it up, a workflow older than some of the engineers reading this sentence and one that still works precisely because there is nothing in it that can break. The application code looks like this on any plan that can run PHP at all:</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-php" data-lang="php"><span style="display:flex;"><span><span style="color:#66d9ef">use</span> <span style="color:#a6e22e">Visorcraft\MongrelDB\Database</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$db <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Database</span>(<span style="color:#e6db74">&#39;https://db.internal.example.com:8453&#39;</span>, <span style="color:#a6e22e">token</span><span style="color:#f92672">:</span> $token);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$db<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">createTable</span>(<span style="color:#e6db74">&#39;orders&#39;</span>, [
</span></span><span style="display:flex;"><span>    [<span style="color:#e6db74">&#39;id&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>, <span style="color:#e6db74">&#39;name&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;id&#39;</span>,    <span style="color:#e6db74">&#39;ty&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;int64&#39;</span>,   <span style="color:#e6db74">&#39;primary_key&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">true</span>,  <span style="color:#e6db74">&#39;nullable&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>],
</span></span><span style="display:flex;"><span>    [<span style="color:#e6db74">&#39;id&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">2</span>, <span style="color:#e6db74">&#39;name&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;email&#39;</span>, <span style="color:#e6db74">&#39;ty&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;varchar&#39;</span>, <span style="color:#e6db74">&#39;primary_key&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>, <span style="color:#e6db74">&#39;nullable&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>],
</span></span><span style="display:flex;"><span>    [<span style="color:#e6db74">&#39;id&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">3</span>, <span style="color:#e6db74">&#39;name&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;total&#39;</span>, <span style="color:#e6db74">&#39;ty&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;float64&#39;</span>, <span style="color:#e6db74">&#39;primary_key&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>, <span style="color:#e6db74">&#39;nullable&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>],
</span></span><span style="display:flex;"><span>]);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$db<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">put</span>(<span style="color:#e6db74">&#39;orders&#39;</span>, [<span style="color:#ae81ff">1</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;alice@example.com&#39;</span>, <span style="color:#ae81ff">3</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">49.99</span>]);
</span></span></code></pre></div><h2 id="where-the-database-lives-then">Where the database lives, then</h2>
<p>The client speaks plain HTTP to a <code>mongreldb-server</code> daemon, and that single fact is what makes the shared-hosting story work, because the daemon does not have to live on the plan at all. It runs wherever you control something: a small VPS, a container next to your other services, a mini PC in the agency&rsquo;s office closet, and the PHP side stays exactly where the customer&rsquo;s budget already put it, talking to the daemon over keep-alive connections with a bearer token and an IP allowlist standing in for the old &ldquo;localhost is the security model&rdquo; assumption.</p>
<p>In 2005 we colocated MySQL with the app because the network was the trust boundary and the host gave us both on one box; the modern equivalent is a daemon you own on a network you control, and the difference is that the cheap plan no longer has to provide the database for the arrangement to feel just as simple.</p>
<h2 id="the-honest-part">The honest part</h2>
<p>Shared hosting is not secretly good, and pretending otherwise would be nostalgia rather than engineering: outbound requests share a crowded process pool, nothing long-running survives, and every request pays PHP&rsquo;s bootstrap cost, so the client does what it can inside those limits, reusing connections through cURL keep-alive and staging writes into idempotent batch transactions so a unit of work costs one round trip instead of five. If the application outgrows the plan, the same code runs unchanged on FPM, FrankenPHP, or a queue worker somewhere serious, because the transport was HTTP the entire time and nothing about the deployment shape is baked into the client.</p>
<p>That is the whole argument, really: a dependency tree is a product decision, every compiled extension you require quietly deletes the slice of the market that cannot or will not compile it, and a pure PHP client deletes none of it, which is why &ldquo;it runs everywhere PHP runs&rdquo; is still worth saying out loud in 2026.</p>
]]></content:encoded></item></channel></rss>