ImpulseyeImpulseye
FeaturesIntegrationsPricingBlogChangelogIs It Down?
All posts
Engineering

I built myself a tiny ops dashboard. It found 30 real problems in five minutes.

A personal, owner-only page to stop bouncing between the Hetzner, Supabase, and Resend consoles by hand — and it immediately surfaced a stack of real database performance issues I didn't know I had.

July 19, 2026 5 min read

I spend more time than I'd like to admit copying an IP address out of the Hetzner console before every SSH session. So one evening I built myself a small, ugly, owner-only page — and it ended up doing a lot more than save me a few clicks.

TL;DR

Added a personal /ops dashboard (gated so only my account can even load the route) that pulls a few things I check by hand into one place — server status, database health, email activity. The database-health panel surfaces Supabase's own performance advisor, and the first time I opened it, it was sitting on 26 row-level-security policies re-evaluating auth.uid() on every single row instead of once per query, plus a handful of duplicate policies and indexes nobody had noticed. All fixed the same afternoon.

Why bother

None of this was broken in a way anyone would file a bug about. The app worked. Checks ran. Alerts sent. But "works" and "efficient" are different claims, and I only ever look at the second one when something forces me to — which, for a one-person team, is basically never, because there's no coworker whose job it is to ask "hey, did you check the advisor tab lately?"

So instead of relying on remembering to check, I built the check into something I'd actually open: a page that shows me the Hetzner box's CPU/disk/network graphs (so I stop tab-switching to a console just to see if the thing is on fire), a rollup of recent email activity, and — the part that actually mattered — Supabase's security and performance advisors, rendered as a real list instead of a number I have to go look up separately.

What the advisor actually found

The performance advisor's single biggest finding was 26 RLS policies across almost every table — monitors, incidents, profiles, uptime_logs, and half a dozen others — all shaped like this:

sql
-- What every one of these policies looked like
create policy "Users can view own monitors" on monitors
  for select
  using (auth.uid() = user_id);

That reads perfectly reasonably, and it's the version every Supabase tutorial shows you. The problem is what Postgres actually does with it: auth.uid() gets re-evaluated once per row the policy is checked against, instead of once for the whole query. On a small table that's noise. On a 200-row page load it's fine. On the tables that grow without bound in this app — uptime check history, incident logs — it's a cost that scales with data you're specifically hoping accumulates.

The fix is one extra pair of parentheses:

sql
-- Same policy, wrapped so Postgres treats it as a stable value
create policy "Users can view own monitors" on monitors
  for select
  using ((select auth.uid()) = user_id);
Same logic, different plan

Wrapping the call in (select ...) doesn't change what the policy allows — it changes how Postgres plans it, letting the value get computed once and reused instead of recomputed per row. It's Supabase's own documented fix for this exact lint, which is presumably why their advisor knows to flag it by name.

Alongside that, the advisor turned up two smaller things that were pure debt rather than a subtle tradeoff:

  • Three duplicate policies on the monitors table — "Users can insert own monitors" and "Users can insert their own monitors," identical logic, both still active. Leftover from a rename at some point that added the new one without removing the old. Harmless, but Postgres was evaluating both of them, every time, forever.
  • Two identical unique constraints on a rollup table — same columns, same uniqueness guarantee, backed by two separate indexes doing the same job.
A green dashboard tells you the thing works. It doesn't tell you whether it's still working the way you'd choose if you looked today.
- what this made me update in my own head

What I didn't touch

The advisor also flagged a batch of indexes as "unused" — meaning Postgres has recorded zero scans against them since stats were last reset. I left every one of them alone. This app is a few months old and still low-traffic; an index sitting idle right now usually just means the query pattern it exists for hasn't been hit hard yet, not that it was a mistake to add. Dropping it to clear an informational warning, only to need it back the moment real load shows up, is churn with no upside. "The advisor flagged it" isn't the same question as "should I actually change this" — the dashboard's job is to surface the question, not answer it for me.

The actual lesson

None of this was a bug. Nothing was down. Nobody would have ever opened a support ticket about query-plan efficiency on a RLS policy. That's exactly why it sat there for weeks — there was no external pressure forcing me to look. The fix wasn't smarter code, it was building a smaller mirror: one page that shows me the boring, unglamorous health signals I'd otherwise have to remember to go check four different places for, on four different logins, none of which I do for fun.

Cheapest tool I've shipped in a while, and it paid for itself before I'd even finished writing it.

Back to all posts
Share

Monitor your sites with Impulseye

Uptime checks, SSL warnings, and alerts across 9 channels.

Start free

Keep reading

Infrastructure 7 min

My load test was lying to me, and I almost believed it

Before renting a real server, I built a load-testing rig to find Impulseye's actual ceiling. It reported a ceiling that didn't exist — the test harness itself had two bugs, and both of them looked exactly like a capacity problem.

July 14, 2026Read
Postmortem 6 min

The signup bug that almost shipped on launch day

A single trigger wired to the wrong table meant every new signup would have failed — and every digest email would have silently gone nowhere. Here's how I found it before opening the doors.

July 2, 2026Read
Engineering 9 min

What seven webhook providers taught me about shipping alerts

Discord, Slack, Teams, Telegram, Google Chat, PagerDuty, and Pushover each format an alert differently — and each one will silently reject you if you don't respect its limits. Here's what I wish I'd known on day one.

June 28, 2026Read
ImpulseyeImpulseye

Uptime monitoring that is dead simple. Instant alerts via email, Slack, and Discord, set up in under 30 seconds.

support@impulseye.com

Product

  • Features
  • Integrations
  • Pricing
  • Blog
  • Changelog

Tools

  • Is It Down?
  • Dashboard
  • Status Pages
  • Impulseye Status
  • API Docs
  • FAQ

Legal

  • Terms of Service
  • Privacy Policy
  • Refund Policy

© 2026 Impulseye. All rights reserved.

ContactTermsPrivacy