<?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>Supabase on hippotion</title><link>https://blog.hippotion.com/tags/supabase/</link><description>Recent content in Supabase on hippotion</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Fri, 14 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.hippotion.com/tags/supabase/index.xml" rel="self" type="application/rss+xml"/><item><title>Self-hosting the thing I paid not to think about</title><link>https://blog.hippotion.com/posts/self-hosting-supabase-lean/</link><pubDate>Fri, 14 Aug 2026 00:00:00 +0000</pubDate><guid>https://blog.hippotion.com/posts/self-hosting-supabase-lean/</guid><description>A managed service is a deal: you pay to not think about what&amp;rsquo;s underneath. I self-hosted Supabase on a 16GB box over a weekend, with AI help, and made every component earn its place. What I bought back was understanding.</description><content:encoded><![CDATA[<p>I run a small app on <a href="https://supabase.com">Supabase</a> — a kombucha tracker. Hosted Supabase is great
for that: you get a database, auth, an API, a dashboard, and you never think about any of it. That&rsquo;s
the whole pitch — a backend in minutes, don&rsquo;t think about Postgres.</p>
<p>I decided to self-host all of it anyway.</p>
<p>A managed service is a deal. You pay — in money, or in not-knowing — to not think about what&rsquo;s
underneath. Most of the time that&rsquo;s fine. But &ldquo;I use Supabase&rdquo; and &ldquo;I understand Supabase&rdquo; are not
the same sentence, and I wanted to close the gap between them.</p>
<h2 id="how-i-actually-did-this">How I actually did this</h2>
<p>I should be honest about the method, because it&rsquo;s the point as much as the result.</p>
<p>I did this over one weekend, in the gaps around family time. And I didn&rsquo;t hand-type every line — I
paired with an AI assistant (Claude) to move fast. It wrote a lot of the Kubernetes manifests, and we
debugged the failures together; I made the calls on what to run and checked that the result was real.
Without that help I would not have fit a job like this into a weekend with two kids in the house. It
just wouldn&rsquo;t have happened.</p>
<p>That matters for the rest of the post. The AI bought me the time. It did not buy me the
understanding — that part you still have to do yourself, by deciding things and watching them break.
What changed is that the understanding became affordable. A few years ago this would have been a
month of evenings. Now it&rsquo;s a Saturday.</p>
<h2 id="the-constraint-made-me-deliberate">The constraint made me deliberate</h2>
<p>My homelab is one mini-PC with 16 GB of RAM, and it already runs everything else I use. Supabase is
about ten services. All of that does not fit on that box.</p>
<p>On a small box you can&rsquo;t just install everything and move on. Every component has to earn its RAM.
And to decide whether a piece earns its keep, you have to understand what it is for. The limit turned
a shrug into a list of real questions.</p>
<p>So I didn&rsquo;t deploy Supabase. I assembled it.</p>
<ul>
<li><strong>Postgres, the auto-generated REST API, auth, the Studio dashboard, a gateway</strong> — the core. This
is the part that makes it Supabase and not just a database. Non-negotiable.</li>
<li><strong>The log pipeline (Logflare and a collector)</strong> — I left this out first, to save memory. Then I
tried to actually operate the thing and realised you can&rsquo;t run what you can&rsquo;t see. It earned its
place the moment I needed to know what was happening inside the box, so it went back in. Now the
dashboard&rsquo;s Logs and Reports work.</li>
<li><strong>Realtime, storage, image proxy, edge functions</strong> — real and useful, and switched off. Nothing I
run needs them yet, so they don&rsquo;t get to take memory the rest of the cluster wants.</li>
</ul>
<p>Even trimmed to eight components, this is not free. With Supabase running, the node sits at about
70% memory, and to make the room I had to switch my media server off — scaled to zero — where it
stays until I scale Supabase back down. That is the actual price of the lesson, and it is a number,
not a feeling.</p>
<p>That list is not a compromise forced by a small box. It is a set of decisions I could not have made
before I was forced to make them. As a hosted user I never once asked &ldquo;does this component earn its
place?&rdquo; I got all of it, and I never had to know what any of it was for.</p>
<h2 id="then-i-moved-a-real-app-onto-it">Then I moved a real app onto it</h2>
<p>A self-hosted database proves nothing until something real depends on it. So I moved the kombucha app
off its own bundled Postgres and onto the self-hosted Supabase — dumped the data across, repointed
the app, switched the old database off.</p>
<p>Studio immediately showed no tables. The data was there; the dashboard could not see it.</p>
<p>That bug taught me more than the deploy did. Supabase works on a single database by design — Studio,
the auto-API, and auth all use one database called <code>postgres</code>. I had put my app in a separate
database. Postgres was fine with that, but it made the app invisible to everything that makes Supabase
Supabase. Move the tables into the <code>postgres</code> database&rsquo;s public schema and the dashboard sees them and
the API builds itself over them. You do not learn that from the docs. You learn it when the
convenience you expected quietly does not happen.</p>
<h2 id="the-bugs-were-the-lessons">The bugs were the lessons</h2>
<p>None of it came up clean the first time, and that was the useful part. Each failure was a piece of how
it really works:</p>
<ul>
<li>The edge-functions runtime kept crashing because it starts by downloading a module from the
internet, which my network policy blocks. It turned out I did not need it running at all, only a
volume it leaves behind. So I turned it off.</li>
<li>The log collector stayed silent because it finds what to collect by talking to the Kubernetes API,
which my deny-by-default policy also blocked. A log shipper needs API access, not just the app
ports. Obvious afterwards, invisible until nothing showed up.</li>
<li>The <code>postgres</code> user is not actually a superuser. Supabase keeps the real one to itself. &ldquo;postgres&rdquo;
does not always mean root.</li>
</ul>
<p>Each of those is now something I know, instead of something I trust the platform to handle.</p>
<h2 id="what-the-deal-was-worth">What the deal was worth</h2>
<p>Hosted Supabase sells you the time you don&rsquo;t spend on all of this. That is a fair price and most days
I would pay it.</p>
<p>There is an obvious objection here and it is a good one, so let me say it before someone else does: a
managed service does not take your understanding away. Being a passive user does. You can run hosted
Supabase and know it very well — through migrations, incidents, restores, the bill, and the limits you
find at the edges. Self-hosting is not the only way to stop being passive. It is just the way that
works on me, because it does not let me skip anything.</p>
<p>I should also be honest about what one weekend actually bought. Not &ldquo;I understand Supabase.&rdquo; I ran a
reduced version of it, on one node, with one small app and no real traffic. What I have now is the
component boundaries and the four failure modes I hit myself. That is a lot more than I had as a
hosted user, and a lot less than running it in production would teach me.</p>
<p>It still changed something. Supabase stopped being a product I use and became a system whose parts I
can name: a Postgres, with a small ring of services that make it do more than a plain database should,
each one there because I decided it earned the space.</p>
<p>That is the trade I wanted. Not the time saved — the understanding the saved time was hiding.</p>
]]></content:encoded></item></channel></rss>