Remindlo: SMS and email reminders that send themselves
A product I build and operate myself. Appointments arrive from the business's calendar, reminders go out by SMS and email on schedule, and every message is accounted for, including the ones the network failed to deliver.
- Problem
- Service businesses lose customers between visits: the MOT, the dental check-up or the vaccination falls due and nobody reminds them. Doing it by hand means a spreadsheet and an afternoon of texts.
- What runs
- Calendar pollers every 5 to 10 minutes, a campaign engine that decides who is due, SMS through two providers, a daily job that rolls recurring services forward, a monthly recap by email.
- How it is watched
- A delivery receipt on every SMS, browser errors in Sentry, a nightly backup that is restored and compared before it is kept, and a known-issues list for what the system still gets wrong.
- Stack
- React, Supabase (Postgres with row-level security, Deno Edge Functions, pg_cron), Twilio and Telnyx, Resend, Stripe, Cloudflare Workers.
- Code
- Private repository. A walkthrough is available on request.
The problem
A garage, a clinic or a salon earns most of its money from people who have been before. The next visit is predictable: twelve months after the MOT, six months after the check-up. The reminder that brings them back is the part that gets skipped, because it depends on someone remembering to send it.
Remindlo sends automatic SMS and email reminders for service businesses. I built it and I run it, so this page is the same kind of automation I build for clients, seen from the operator's side.
What it does
- Reads appointments from where the business already keeps them: Google Calendar, Outlook and Microsoft 365, iCloud or any ICS feed. A Google Calendar add-on works from inside the calendar.
- Runs campaigns defined as offsets: N days before the next visit is due, or N days after the last one. The scheduling lives in Postgres triggers, so a change to a visit recalculates the next send in the same transaction.
- Rolls recurring services forward every night: when an annual service date passes, the next one is set a year later and the reminders follow.
- Sends SMS through Twilio, or through Telnyx for North American numbers, each provider the other's fallback. Replies and STOP messages come back through signed webhooks.
- Has a public REST API, webhooks and an MCP server, so other systems and AI assistants can add contacts and send messages.
How it stays under control
- Every SMS gets a delivery receipt. The status is the network's answer, and a reminder sent to a landline shows up as failed instead of as done.
- A message is sent once, even when it is requested twice. Four parts of the system can ask for the same send. The sender claims the message with one conditional database update before calling the provider, and a caller that loses the claim treats it as "not mine" rather than as an error.
- Anything that must happen once per signup happens in the database, not in the browser, so a closed tab cannot leave a half-created account.
- The backup is tested every night. The database is dumped, checked for truncation, loaded into an empty database and compared table by table, then encrypted and stored separately.
- Public numbers have a source. The figure on the site is 89.0% of reminders confirmed delivered by the network: 719 messages that had a receipt, out of 753 sent by 93 businesses, measured on 3 October 2026. The method and the failures behind it are published on Remindlo's evidence page.
Sending exactly once
UPDATE messages
SET claimed_at = now()
WHERE id = $1
AND status = 'queued'
AND (claimed_at IS NULL
OR claimed_at < now() - interval '5 minutes')
RETURNING id;
-- no row back: another caller owns this send
-- answer 200 {"skipped": true}, not an errorScreenshots
What a business could reuse from this
Any business with recurring visits, renewals or due dates: services, inspections, memberships, contracts. The same parts apply to client work: read the calendar or system the business already uses, keep the schedule in the database, and record what actually happened to every message.