← Blog

Monitor your SaaS on Vercel — health URL + status page

Vercel makes shipping a Next.js frontend trivial: git push, preview URLs, edge or Node runtimes in one dashboard. Production still needs a health endpoint the world can ping without your session cookie, and an external monitor that is not your browser tab — otherwise marketing pages can look green while /api returns 503.

StillOnline probes your production health URL on a schedule, auto-builds a status page, and alerts you on email, Telegram (StillOnline bot), or Slack when checks fail. This walkthrough uses the App Router (app/api/health/route.ts), deploys to a Vercel URL, and registers a StillOnline check. Generic steps: Health check quickstart. Railway: Railway guide.

Quick answer

On Vercel, add app/api/health/route.ts (dynamic GET returning 200), deploy, then point a StillOnline HTTP check at https://your-app.vercel.app/api/health (or your custom domain). StillOnline probes from the internet every 5 minutes on Free and auto-creates a status page. Exclude /api/health from auth middleware; enable Telegram or Slack owner alerts in settings.

1. Add app/api/health/route.ts

A route handler is the right surface for probes: you control JSON, status codes, and whether the database is included. Keep the handler dynamic if you touch the database — static optimization can cache a stale “ok” while Postgres is down.

import { NextResponse } from "next/server";

export const dynamic = "force-dynamic";

export async function GET() {
  let db: "ok" | "error" = "ok";

  try {
    // Optional: await prisma.$queryRaw`SELECT 1`;
    // Remove DB ping for pure liveness on Free-tier hobby DBs.
  } catch {
    db = "error";
  }

  const healthy = db === "ok";
  const status = healthy ? "ok" : "degraded";

  return NextResponse.json(
    {
      status,
      service: "my-saas",
      db,
      timestamp: new Date().toISOString(),
    },
    { status: healthy ? 200 : 503 },
  );
}

Trade-off: returning 503 when Postgres has a brief outage marks you down on StillOnline — correct for “API not usable,” noisy during migrations. For liveness only, return 200 and omit the DB block.

2. Deploy on Vercel

Connect the Git repo, set the production branch, and add env vars (DATABASE_URL, etc.) in the Vercel dashboard. Note the production host: https://your-app.vercel.app or your custom domain.

Before StillOnline, prove the route from your laptop:

curl -sS https://your-app.vercel.app/api/health

You want JSON and HTTP 200 on the same hostname you will paste into StillOnline.

3. Avoid typical Vercel mistakes

Middleware, runtime choice, and preview protection are the usual reasons external checks fail while the Vercel UI looks fine.

ProblemSolution
Middleware blocks /api/healthExclude path in middleware.ts matcher
Edge runtime without DB driverUse Node runtime for DB health or skip DB
Deployment protection on previewsMonitor production URL only
Redirect www → apexUse the final HTTPS URL in StillOnline

4. StillOnline check (five clicks)

Register the exact URL you curled — StillOnline does not deploy to Vercel and does not read Vercel logs.

  1. Start free.
  2. Create project + status slug.
  3. HTTP check → https://your-app.vercel.app/api/health (or custom domain), expect 200, 5 min interval.
  4. Save https://stillonline.tech/s/{slug} for docs, onboarding, and support — not the site footer.
  5. Optional Pro: MCP to recreate checks after domain changes.

Free: 1 URL, 24h history. Pro $9/mo: 10 URLs, private pages, API/MCP, 90d history — Pricing.

Owner alerts: when the check fails or recovers, enable email, Telegram, or Slack in account settings — one channel on Free, all three on Pro / Ultimate. Guides: Telegram · Slack.

5. When Vercel is up but you are “down”

Green deploy status does not guarantee happy users. These gaps show up often on serverless stacks — document them on your status page when needed.

  • Serverless cold start — rare timeouts; increase monitor timeout tolerance or warm critical paths.
  • Region-only outage — single-region Vercel + single monitor = blind spot; advanced teams add a second check from another vendor (comparison post).
  • Third-party API — health should reflect your SLA, not Stripe’s; document external deps on the status page manually via incidents.

Related guides

FAQ

Should StillOnline monitor a Vercel Route Handler or a Server Component page?

Use a Route Handler at app/api/health/route.ts with export const dynamic = "force-dynamic" for probes. Marketing pages can SSR-cache a misleading “ok” while the API is broken—StillOnline only sees the URL you register.

Should my StillOnline check target Vercel marketing or /api/health?

Monitor /api/health (or your real API path) if paying users depend on the API. The marketing site on Vercel can stay green while DATABASE_URL is wrong on the API deployment. Share the StillOnline status page in docs, not the site footer.

Does Vercel Speed Insights replace StillOnline uptime monitoring?

No. Speed Insights samples performance; StillOnline HTTP checks drive availability, history, and owner alerts. For landing-page CWV over time, use StillOnline Page Speed on public URLs—not your API health route.

Can I copy StillOnline’s own Vercel health pattern?

StillOnline production uses JSON health with an optional DB ping at api/health—your handler can be simpler. Register the final production HTTPS URL in StillOnline after curl succeeds; see health quickstart.