Monitoring Your Qwik/QwikCity Application with Vigilmon
Qwik's resumability model means your app boots fast. That's great for users — but it doesn't protect you from the moment your server goes down or your deployment breaks. You still need an external eye watching your production URL around the clock.
This tutorial walks through:
- A
/healthserver route in QwikCity - An HTTP uptime monitor in Vigilmon
- A keyword monitor that confirms your app is actually rendering
- Slack or email alerts when anything goes wrong
The full setup takes about 15 minutes.
Step 1: Add a health endpoint in QwikCity
QwikCity uses file-based routing. Server routes live in src/routes/ and export request handlers. Add a health/ route that returns a JSON status:
// src/routes/health/index.ts
import type { RequestHandler } from '@builder.io/qwik-city';
export const onGet: RequestHandler = ({ json }) => {
json(200, {
status: 'ok',
service: 'qwik-app',
timestamp: new Date().toISOString(),
});
};
Start your dev server and verify:
npm run dev
curl http://localhost:5173/health
# {"status":"ok","service":"qwik-app","timestamp":"..."}
For a deeper health check that exercises your data layer:
// src/routes/health/index.ts
import type { RequestHandler } from '@builder.io/qwik-city';
export const onGet: RequestHandler = async ({ json, env }) => {
const checks: Record<string, string> = {};
let healthy = true;
// Example: check a database or external API
try {
const dbUrl = env.get('DATABASE_URL');
if (dbUrl) {
// perform a lightweight ping query here
checks['database'] = 'ok';
}
} catch {
checks['database'] = 'error';
healthy = false;
}
json(healthy ? 200 : 503, {
status: healthy ? 'ok' : 'degraded',
checks,
timestamp: new Date().toISOString(),
});
};
A 503 on failure means Vigilmon will detect the outage immediately without needing a body check.
Step 2: Set up an HTTP monitor in Vigilmon
Deploy your QwikCity app (Node adapter, Cloudflare Pages, Vercel, etc.) then connect it to Vigilmon:
- Sign up at vigilmon.online — free, no card required
- Click New Monitor → HTTP
- URL:
https://yourapp.example.com/health - Check interval: 1 minute (paid) or 5 minutes (free)
- Expected status:
200 - Save
Vigilmon probes from multiple regions. If your /health route returns anything other than 200 — or times out — you get alerted immediately.
Step 3: Add a keyword monitor for the home page
Your health endpoint checks the server. A keyword monitor checks that your Qwik app is actually rendering HTML correctly — critical since Qwik's HTML-streaming output could silently break during a bad deploy.
In Vigilmon:
- Click New Monitor → Keyword
- URL:
https://yourapp.example.com/ - Keyword: your app name, a nav label, or any static string that appears in every render
- Match type: Contains
- Expected status:
200 - Save
If your deploy breaks the rendering pipeline but leaves the server running, the HTTP monitor stays green — only the keyword monitor catches it.
Step 4: Configure alerts
Go to Notifications → New Channel in Vigilmon and pick your channel type:
Slack:
- Create an incoming webhook at api.slack.com/apps
- Paste the URL into Vigilmon's Slack channel config
- Enable it on both your monitors
Email:
- Add your email address as a notification channel
- Enable it on the monitors you want coverage for
When your Qwik app goes down, the alert lands within the check interval:
🔴 DOWN: yourapp.example.com/health
Status: 503
Region: EU-West
3 minutes ago
When it recovers:
✅ RECOVERED: yourapp.example.com/health
Downtime: 6 minutes
For critical production apps, enable both Slack (immediate) and email (paper trail).
Step 5: Heartbeat monitoring for Qwik build jobs or cron tasks
If you run scheduled tasks alongside your QwikCity app — revalidation jobs, data sync, cron endpoints — HTTP monitoring won't catch a silent failure there.
Use QwikCity's onRequest to create a cron-compatible endpoint that pings a Vigilmon heartbeat on success:
// src/routes/api/cron/sync/index.ts
import type { RequestHandler } from '@builder.io/qwik-city';
export const onPost: RequestHandler = async ({ json, env }) => {
try {
await runDataSync();
const heartbeatUrl = env.get('VIGILMON_SYNC_HEARTBEAT');
if (heartbeatUrl) {
await fetch(heartbeatUrl);
}
json(200, { status: 'synced' });
} catch (err) {
json(500, { status: 'error', message: String(err) });
}
};
async function runDataSync() {
// your sync logic
}
In Vigilmon, create a Heartbeat Monitor:
- Click New Monitor → Heartbeat
- Set the expected interval to match your job schedule
- Copy the ping URL
- Set
VIGILMON_SYNC_HEARTBEAT=<url>in your environment
If the job stops running or throws, Vigilmon alerts you after one missed interval.
Step 6: Public status page
Go to Status Pages → New Status Page in Vigilmon, add your monitors, and publish. Drop the URL in your README or error pages so users can self-check:
Service unavailable. Check our status page: https://status.yourapp.example.com
Each monitor also generates a live badge:

What you've built
| What | How |
|------|-----|
| Health endpoint | QwikCity server route at /health |
| HTTP uptime check | Vigilmon HTTP monitor |
| Rendering check | Vigilmon keyword monitor on home page |
| Slack/email alerts | Vigilmon notification channels |
| Cron job monitoring | Heartbeat ping in scheduled handler |
| Status page | Vigilmon public status page |
Your Qwik app is fast. Now it's also visible when it breaks.
Next steps
- Add check-specific monitors for any critical API routes your app depends on
- Watch response time trends — Vigilmon charts latency over time, and gradual slowdowns are often visible before a full outage
- Add a heartbeat for every background job, not just the main one
Get started free at vigilmon.online.