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 },
},
});
} 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() });
} 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
- Go to vigilmon.online
- Click Add Monitor
-
Configure:
- URL: https://yourdomain.com/health
- Method: GET
- Expected status: 200
- Check interval: 1 minute
Add SSL certificate monitoring for your domain
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)