Monitoring Your Strapi CMS with Vigilmon (Free, Multi-Region)
Strapi is the go-to open-source headless CMS for teams that want full control over their content API. When it works, it's invisible — your Next.js front end, mobile app, and marketing site all pull content seamlessly.
When it goes down, all of them break at once.
This guide covers how to expose Strapi's built-in health endpoints, set up external uptime monitoring from multiple regions with Vigilmon, and get alerted the moment something goes wrong — before a client or user tells you.
Why Strapi monitoring is different from a regular web app
Strapi is infrastructure. A typical SaaS app only breaks users of that one app. Strapi outages cascade:
- Frontend sites return empty pages or crash entirely
- E-commerce storefronts lose product data
- Mobile apps fail to load dynamic content
- Scheduled content publishes are silently missed
Standard process monitors won't catch this. You need external checks that verify Strapi is actually accepting HTTP requests and returning valid responses.
Step 1: Understand Strapi's health endpoints
Strapi ships with two built-in health routes. No code needed — they're ready out of the box.
/_health
The primary health endpoint. Returns HTTP 200 with a plain text response when Strapi is running:
curl https://your-strapi.com/_health
# Strapi is alive
Returns 503 or a connection error when Strapi is down. This is the endpoint you'll point your external monitor at.
/api/health (Strapi v5+)
Starting with Strapi v5, there's a JSON-formatted health route under /api/health:
curl https://your-strapi.com/api/health
# {"status":"healthy","time":"2026-06-30T08:00:00.000Z","degraded":false}
If you're on v5+, prefer this endpoint — the structured JSON lets you assert on the response body, not just the HTTP status code.
Verify your database is included
The built-in health endpoints confirm the Node.js process is alive but don't always surface database connectivity issues. To catch DB failures, add a lightweight custom health route:
// src/api/health/routes/health.js
module.exports = {
routes: [
{
method: 'GET',
path: '/health/detailed',
handler: 'health.check',
config: { auth: false },
},
],
};
// src/api/health/controllers/health.js
module.exports = {
async check(ctx) {
try {
// Test database connectivity
await strapi.db.connection.raw('SELECT 1');
ctx.body = { status: 'ok', database: 'ok' };
} catch (err) {
ctx.status = 503;
ctx.body = { status: 'degraded', database: 'error', detail: err.message };
}
},
};
curl https://your-strapi.com/health/detailed
# {"status":"ok","database":"ok"}
Step 2: Set up Vigilmon HTTP monitoring
With your health endpoint live, point Vigilmon at it:
- Sign up at vigilmon.online — free tier, no credit card required
- Click New Monitor → HTTP
- Enter
https://your-strapi.com/_health(or/api/healthfor v5+) - Set the check interval (5 minutes on the free tier)
- Save
Vigilmon probes from multiple geographic regions simultaneously. If your Strapi instance is unreachable from any region, it opens an incident immediately.
Add a keyword monitor for deeper assurance
For Strapi v5's JSON response, add a second monitor with keyword matching:
- New Monitor → Keyword
- URL:
https://your-strapi.com/api/health - Keyword to match:
"status":"healthy" - If the keyword is absent, Vigilmon treats it as a failure
This catches the edge case where Strapi returns HTTP 200 but serves an error page or garbled output — which can happen after a failed plugin load.
Recommended monitor set for Strapi
| Monitor | URL | Type | What it catches |
|---|---|---|---|
| Strapi health | /_health | HTTP | Process down, port not listening |
| API health (v5+) | /api/health | Keyword | Degraded startup, plugin errors |
| Database health | /health/detailed | Keyword | PostgreSQL/MySQL/SQLite down |
| Admin panel | /admin | HTTP | Admin UI broken (bad deploy) |
Step 3: Monitor scheduled content publishing
Strapi's scheduled publishing feature silently fails when something goes wrong with the cron internals. Catch this with heartbeat monitoring.
Create a custom scheduled job that pings Vigilmon on each successful publish cycle:
// config/cron-tasks.js
const axios = require('axios');
module.exports = {
publishHeartbeat: {
task: async ({ strapi }) => {
try {
// Find and publish any content scheduled for now
const now = new Date();
const scheduled = await strapi.db.query('api::article.article').findMany({
where: {
publishedAt: null,
scheduledAt: { $lte: now },
},
});
for (const item of scheduled) {
await strapi.entityService.update('api::article.article', item.id, {
data: { publishedAt: now },
});
}
// Ping heartbeat only on success
const heartbeatUrl = process.env.PUBLISH_HEARTBEAT_URL;
if (heartbeatUrl) {
await axios.get(heartbeatUrl, { timeout: 10000 });
}
} catch (err) {
strapi.log.error('publishHeartbeat failed:', err);
// No ping — the missed ping is the alert
}
},
options: {
rule: '*/5 * * * *', // every 5 minutes
},
},
};
In Vigilmon:
- New Monitor → Heartbeat
- Set the expected interval to 10 minutes (double the cron interval — gives you a buffer)
- Copy the unique ping URL
- Add to your environment:
# .env
PUBLISH_HEARTBEAT_URL=https://vigilmon.online/api/heartbeat/your-unique-token
Now if the scheduled publish cron stops firing — because Strapi crashed and restarted, or the cron plugin threw an error — Vigilmon alerts you within one missed interval.
Step 4: Configure alert delivery
Set up where Vigilmon sends alerts when Strapi goes down.
Slack:
- Create an incoming webhook in your Slack workspace
- In Vigilmon: Notifications → New Channel → Slack
- Paste your webhook URL and enable it on your monitors
Email:
- In Vigilmon: Notifications → New Channel → Email
- Add your email address (or your whole team's)
When Strapi goes down, you'll receive:
🔴 DOWN: your-strapi.com/_health
Status: Connection refused
Regions: US-East, EU-West, AP-Southeast
Started: 2 minutes ago
And recovery:
✅ RECOVERED: your-strapi.com/_health is back UP
Total downtime: 6 minutes
Step 5: Create a public status page
Strapi powers public-facing content. Your content team and external developers using your API deserve visibility into uptime.
In Vigilmon:
- Status Pages → New Status Page
- Name it (e.g. "Content API Status")
- Add your Strapi health monitors
- Save and copy the public URL
Add the status page URL to your developer docs, your Strapi admin welcome message, or your README:
## API Status
Real-time status: https://status.yourdomain.com
Step 6: Self-hosted Strapi — docker-compose health checks
If you run Strapi via Docker, wire up a container-level health check so failed containers are restarted automatically:
# docker-compose.yml
services:
strapi:
image: your-strapi-image
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:1337/_health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
restart: unless-stopped
This gives you two layers:
- Docker restarts the container if it becomes unhealthy
- Vigilmon alerts you if the whole host is unreachable or the restart loop isn't resolving the issue
What you've built
| What | How |
|---|---|
| Built-in health check | /_health or /api/health — no code needed |
| Database health | Custom /health/detailed route with DB query |
| External uptime monitoring | Vigilmon HTTP monitor (multi-region) |
| Content publish monitoring | Heartbeat ping after each successful cron run |
| Instant alerts | Slack/email notifications on down + recovery |
| Public status page | Vigilmon status page for your API consumers |
| Container health | Docker Compose healthcheck directive |
Your Strapi instance is now visible. The next time the Node.js process crashes, the database connection pool exhausts, or a bad deploy breaks the admin panel, you'll know about it in under five minutes.
Get started free at vigilmon.online — your first monitor is running in under a minute.