How to catch Vercel and Supabase outages before your users do (Better Stack uptime + heartbeat monitoring)

Most of the errors on FixStack are found by a user first: a 500 FUNCTION_INVOCATION_FAILED, a 504 FUNCTION_INVOCATION_TIMEOUT, an Edge Function returning a non-2xx status, or a deploy that quietly 404s. Monitoring flips that around: you get the alert, not the angry email.

This guide uses Better Stack Uptime. Its free tier (per its product page at time of writing) includes 10 monitors, 10 heartbeats and a status page with 3-minute checks, which is enough for a typical Lovable, Bolt, or Next.js + Supabase app.

1. Add a health endpoint

A dedicated route lets a monitor test that your app and its database actually respond, not just that a static page loads.

// app/api/health/route.js  (Next.js App Router)
export const dynamic = 'force-dynamic';

export async function GET() {
  try {
    // Optional: check a dependency, e.g. a cheap Supabase query
    // const { error } = await supabase.from('profiles').select('id').limit(1);
    // if (error) throw error;
    return Response.json({ ok: true });
  } catch (err) {
    console.error(err);
    return Response.json({ ok: false }, { status: 500 });
  }
}

2. Create uptime monitors

  1. Sign up at Better Stack and create a monitor for your homepage URL.
  2. Create a second monitor for https://yourdomain.com/api/health, so you are alerted when it stops returning a success status.
  3. Choose how you want to be alerted (email, Slack, SMS, phone call or push, depending on plan).

Better Stack records the error response and a screenshot when a check fails, which helps you match the failure to the right FixStack page.

3. Monitor cron jobs with heartbeats

Scheduled jobs (Vercel Cron, Supabase scheduled functions, backups) fail silently: nothing errors on a page, the job just doesn't run. A heartbeat monitor gives you a URL to request each time the job succeeds; if the request doesn't arrive on schedule, you get alerted.

// At the END of your scheduled job, after it succeeds:
await fetch(process.env.HEARTBEAT_URL, { signal: AbortSignal.timeout(10000) });

4. Add a status page (optional)

A public status page lets customers check for incidents instead of emailing you, and can be hosted on a subdomain such as status.yourdomain.com.

Which FixStack errors this catches

FixStack is not currently paid by Better Stack. If that changes, links will be marked per our disclosure policy.