supabase-pings
One binary so a free-tier database stops pausing itself.
Go
- YAML
- Slack
- SMTP
- 853
- Lines of Go
- 3
- Alert channels
- Many
- Projects per instance
The problem
Free-tier Supabase projects pause after a week without activity, and an unpaused project is one scheduled request away. Doing that for several projects at once needs a list, a schedule, and somewhere to put credentials that is not the list.
What I built
A Go binary that reads a project list and an interval from one YAML file, notification settings from another, and every secret from the environment. On a failure it can alert over Slack, a transactional email API, or plain SMTP.
Decisions I'd defend
The YAML files hold environment variable names, not values. That is the whole design: the config you commit describes which projects exist and where their credentials live, and the credentials themselves never enter the repository. Disabled channels skip their lookups entirely, so running Slack-only does not require email credentials to exist.
Missing configuration is reported all at once. The earlier tool exited on the first missing variable, which meant fixing one variable per restart; here the resolver accumulates every missing name and reports them together.
Responses are read through a size limit and every interpolated value in the alert email is HTML-escaped. A monitor reads output from something that is already misbehaving, and putting an unbounded, unescaped response body into an alert is how a broken endpoint becomes a second problem.
The one test covers MIME assembly, by re-parsing the generated message and asserting the plain-text part precedes the HTML part. That ordering is a rule of the format rather than a preference, and it is the kind of thing that silently renders wrong in one client and fine in every other.
The tradeoffs
Projects are pinged sequentially, so one unreachable project delays the rest by its timeout. Nothing is persisted between ticks, which means alerts repeat every interval while a project is down and there is no recovery notification. The ticker does not catch up after the host sleeps.
Test coverage is one function. The README says all of this too.
Where it is now
Public and MIT licensed. It is the second pass at the problem the healthcheck monitor introduced me to, and most of what it does differently is a direct response to something the first one got wrong.