DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Your SvelteKit API Routes with Vigilmon

How to Monitor Your SvelteKit API Routes with Vigilmon

SvelteKit's server-side capabilities-API routes, load functions, form actions-mean your SvelteKit app isn't just a frontend. It's a full-stack application with endpoints that can go down. This guide covers health endpoints for SvelteKit and setting up Vigilmon monitoring.

SvelteKit Server Routes Overview

SvelteKit handles server-side logic in +server.ts files (API routes) and +page.server.ts files (load functions and actions). External monitors like Vigilmon check your HTTP endpoints-specifically your API routes.

Creating a Health Endpoint

` ypescript
// src/routes/health/+server.ts
import type { RequestHandler } from "@sveltejs/kit";
import { json } from "@sveltejs/kit";

export const GET: RequestHandler = async () => {
return json({
status: "ok",
timestamp: new Date().toISOString(),
uptime: process.uptime(),
});
};
`

Vigilmon hits https://yourdomain.com/health and receives JSON.

Health Check with Database Connectivity

Prisma

` ypescript
// src/routes/health/+server.ts
import type { RequestHandler } from "@sveltejs/kit";
import { json, error } from "@sveltejs/kit";
import { db } from "/server/db"; // Your Prisma client

export const GET: RequestHandler = async () => {
const start = Date.now();

try {
await db.SELECT 1;
const dbLatency = Date.now() - start;

return json({
  status: "ok",
  timestamp: new Date().toISOString(),
  components: {
    database: { status: "ok", latencyMs: dbLatency },
  },
});
Enter fullscreen mode Exit fullscreen mode

} catch (err) {
return json(
{
status: "error",
timestamp: new Date().toISOString(),
components: {
database: {
status: "error",
error: err instanceof Error ? err.message : "Database connection failed",
},
},
},
{ status: 503 }
);
}
};
`

Drizzle ORM

` ypescript
// src/routes/health/+server.ts
import { json } from "@sveltejs/kit";
import type { RequestHandler } from "@sveltejs/kit";
import { sql } from "drizzle-orm";
import { db } from "/server/db";

export const GET: RequestHandler = async () => {
try {
await db.execute(sqlSELECT 1);

return json({ status: "ok", timestamp: new Date().toISOString() });
Enter fullscreen mode Exit fullscreen mode

} catch {
return json({ status: "error" }, { status: 503 });
}
};
`

Multi-Component Health Check

` ypescript
// src/routes/health/+server.ts
import { json } from "@sveltejs/kit";
import type { RequestHandler } from "@sveltejs/kit";
import { db } from "/server/db";
import { redis } from "/server/redis";

type ComponentStatus = { status: "ok" | "error"; latencyMs?: number; error?: string };

async function checkDatabase(): Promise {
const start = Date.now();
try {
await db.SELECT 1;
return { status: "ok", latencyMs: Date.now() - start };
} catch (e) {
return { status: "error", error: String(e) };
}
}

async function checkRedis(): Promise {
const start = Date.now();
try {
await redis.ping();
return { status: "ok", latencyMs: Date.now() - start };
} catch (e) {
return { status: "error", error: String(e) };
}
}

export const GET: RequestHandler = async () => {
const [database, cache] = await Promise.allSettled([
checkDatabase(),
checkRedis(),
]);

const db_result = database.status === "fulfilled" ? database.value : { status: "error" as const };
const cache_result = cache.status === "fulfilled" ? cache.value : { status: "error" as const };

const allOk = db_result.status === "ok" && cache_result.status === "ok";

return json(
{
status: allOk ? "ok" : "error",
timestamp: new Date().toISOString(),
components: {
database: db_result,
cache: cache_result,
},
},
{ status: allOk ? 200 : 503 }
);
};
`

SvelteKit Adapter Considerations

Node Adapter (Self-hosted)

ash
npm install @sveltejs/adapter-node

`javascript
// svelte.config.js
import adapter from "@sveltejs/adapter-node";

export default {
kit: {
adapter: adapter({
out: "build",
precompress: false,
envPrefix: "",
}),
},
};
`

Your health endpoint works as-is. Run with:
ash
node build/index.js

Vercel Adapter

ash
npm install @sveltejs/adapter-vercel

Health endpoints work as serverless functions on Vercel. Vigilmon monitors them at the production URL.

Cloudflare Pages Adapter

ash
npm install @sveltejs/adapter-cloudflare

Note: process.uptime() is not available in Cloudflare Workers. Simplify your health endpoint:

` ypescript
// src/routes/health/+server.ts
import { json } from "@sveltejs/kit";
import type { RequestHandler } from "@sveltejs/kit";

export const GET: RequestHandler = async () => {
return json({
status: "ok",
timestamp: new Date().toISOString(),
runtime: "cloudflare",
});
};
`

Protecting the Health Endpoint

If you want to expose basic health publicly but require authentication for details:

` ypescript
// src/routes/health/+server.ts
import { json } from "@sveltejs/kit";
import type { RequestHandler } from "@sveltejs/kit";
import { env } from "/dynamic/private";

export const GET: RequestHandler = async ({ request }) => {
const token = request.headers.get("x-health-token");
const detailed = token === env.HEALTH_TOKEN;

const basic = { status: "ok", timestamp: new Date().toISOString() };

if (!detailed) {
return json(basic);
}

// Only with valid token:
return json({
...basic,
uptime: process.uptime(),
memory: process.memoryUsage(),
});
};
`

In Vigilmon, configure the custom header X-Health-Token in your monitor settings.

Setting Up Vigilmon

  1. Go to vigilmon.online
  2. Click Add Monitor
  3. Configure:

  4. Add SSL certificate monitoring for your domain

  5. Connect Slack or email for alerts

Testing Your Health Endpoint

`ash

Local development

curl http://localhost:5173/health

After build

node build/index.js &
curl http://localhost:3000/health

Production

curl https://yourdomain.com/health
`

Expected output:
json
{
"status": "ok",
"timestamp": "2026-08-03T12:00:00.000Z",
"uptime": 42.3
}

SvelteKit-Specific Notes

Prerendering: Health endpoints must NOT be prerendered. They should respond dynamically. Add to your route:

ypescript
export const prerender = false;

CORS: If Vigilmon needs CORS headers (it doesn't for standard HTTP checks, but some configurations do):

ypescript
export const GET: RequestHandler = async () => {
return json({ status: "ok" }, {
headers: {
"Access-Control-Allow-Origin": "*",
},
});
};

Cache headers: Always set Cache-Control: no-store to prevent CDN caching of health responses.

Summary

  • Create src/routes/health/+server.ts as a GET handler
  • Return 200 for healthy, 503 for degraded
  • Add prerender = false to prevent prerendering
  • Test locally before deploying
  • Monitor with Vigilmon for external uptime visibility

Monitor your SvelteKit app at vigilmon.online - free for 3 monitors, no credit card required.

Top comments (0)