Monitoring Your Self-Hosted Appwrite Backend with Vigilmon
Appwrite gives you a full backend in a single Docker deployment — authentication, databases, file storage, cloud functions, and realtime subscriptions. It's the self-hosted alternative to Firebase and Supabase that keeps your data on your own infrastructure.
That self-hosted advantage comes with a responsibility: no one else is watching your uptime. When Appwrite goes down, every app that depends on it stops working. This guide shows you how to set up proper monitoring using Vigilmon so you know about failures before your users do.
What makes Appwrite monitoring distinct
Appwrite is not a single process — it's a set of microservices running as Docker containers:
- appwrite — the core API
- appwrite-worker-* — background workers for functions, mails, webhooks, etc.
- appwrite-executor — runs cloud functions
- mariadb — the primary database
- redis — caching and queues
- influxdb — usage metrics
- traefik — the reverse proxy that routes traffic
A partial failure — say, the functions executor crashes while the core API stays up — looks like "Appwrite is running" from the outside but silently breaks cloud function invocations. You need service-level monitoring, not just a single ping.
Step 1: Explore Appwrite's health API
Appwrite exposes a comprehensive health API at /v1/health. You don't need to write any code — it's built in.
Overall health check
curl https://your-appwrite.com/v1/health
Response when healthy:
{
"ping": 128,
"status": "pass"
}
This confirms the Appwrite API process is alive and responding.
Per-service health endpoints
Appwrite provides granular health checks for each internal service:
# Database (MariaDB)
curl https://your-appwrite.com/v1/health/db
# Cache (Redis)
curl https://your-appwrite.com/v1/health/cache
# Queue (Redis-backed)
curl https://your-appwrite.com/v1/health/queue
# Storage filesystem
curl https://your-appwrite.com/v1/health/storage/local
# Certificate renewal queue
curl https://your-appwrite.com/v1/health/certificate
# Functions execution queue depth
curl https://your-appwrite.com/v1/health/queue/functions
Each returns the same shape:
{ "ping": 45, "status": "pass" }
Or on failure:
{ "ping": 0, "status": "fail" }
Authentication requirement
The /v1/health endpoints require an API key with the health.read scope. Create one:
- Appwrite console → Settings → API Keys → Add API Key
- Name it "monitoring" and enable the
health.readpermission - Copy the key
You'll pass this in the X-Appwrite-Key header.
Step 2: Set up Vigilmon monitors for each service
With the health API explored, set up a monitor per critical service in Vigilmon:
- Sign up at vigilmon.online — free tier, no credit card
- New Monitor → HTTP
For monitors that require authentication headers, use Vigilmon's custom headers:
| Monitor name | URL | Custom header |
|---|---|---|
| Appwrite API | /v1/health | X-Appwrite-Key: your-key |
| Database | /v1/health/db | X-Appwrite-Key: your-key |
| Cache | /v1/health/cache | X-Appwrite-Key: your-key |
| Storage | /v1/health/storage/local | X-Appwrite-Key: your-key |
| Queue | /v1/health/queue | X-Appwrite-Key: your-key |
Add keyword monitors for status assertion
HTTP status alone isn't enough — you want to assert that the response body says "status":"pass", not just that the server returned 200.
For each service monitor, set the Keyword to "status":"pass". If Appwrite returns a 200 but the body says "status":"fail", Vigilmon treats it as an outage.
Step 3: Monitor cloud functions with heartbeats
HTTP endpoint checks confirm Appwrite is running. They won't tell you if a cloud function that runs on a schedule has silently stopped executing.
The heartbeat pattern: your function pings Vigilmon at the end of each successful run. If Vigilmon stops receiving pings within the expected interval, it fires an alert.
Example: Node.js cloud function with heartbeat
// functions/nightly-sync/src/index.js
import { Client, Databases } from 'node-appwrite';
import https from 'https';
export default async ({ req, res, log, error }) => {
try {
const client = new Client()
.setEndpoint(process.env.APPWRITE_FUNCTION_API_ENDPOINT)
.setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID)
.setKey(req.headers['x-appwrite-key']);
const databases = new Databases(client);
// Your actual business logic
const items = await databases.listDocuments('main', 'sync-queue');
log(`Processing ${items.total} items`);
// ... process items ...
// Ping heartbeat only on success
const heartbeatUrl = process.env.SYNC_HEARTBEAT_URL;
if (heartbeatUrl) {
await new Promise((resolve, reject) => {
https.get(heartbeatUrl, resolve).on('error', reject);
});
log('Heartbeat pinged');
}
return res.json({ ok: true, processed: items.total });
} catch (err) {
error(err.message);
// Do NOT ping on failure — the missed ping is the alert
return res.json({ ok: false, error: err.message }, 500);
}
};
Set the environment variable in Appwrite's function settings:
SYNC_HEARTBEAT_URL = https://vigilmon.online/api/heartbeat/your-unique-token
In Vigilmon:
- New Monitor → Heartbeat
- Set the expected interval (e.g., 25 hours for a nightly function)
- Copy the ping URL and add it to your function's env vars
Now if the function crashes, the Appwrite executor goes down, or the function is accidentally deleted, Vigilmon alerts you within one missed interval.
Step 4: Monitor the Appwrite console
The Appwrite web console is separate from the API. Monitor it independently — a broken Traefik configuration or a failed SSL certificate renewal can take down the console while leaving the API accessible.
Add a simple HTTP monitor:
- URL:
https://your-appwrite.com(the console root) - Expected status:
200 - Keyword:
Appwrite(to confirm the right page is loading)
Step 5: Configure alerts
Set up alert channels in Vigilmon so the right people are notified immediately.
Slack:
- Create an incoming webhook in your Slack workspace
- Vigilmon: Notifications → New Channel → Slack
- Paste the webhook URL and enable it on all your Appwrite monitors
PagerDuty or on-call rotation: For production Appwrite deployments, wire Vigilmon into your on-call tool via webhook:
- Vigilmon: Notifications → New Channel → Webhook
- Enter your PagerDuty Events API or on-call webhook URL
When the database goes down:
🔴 DOWN: your-appwrite.com/v1/health/db
Keyword "status":"pass" not found
Regions: US-East, EU-West
Started: 4 minutes ago
When it recovers:
✅ RECOVERED: your-appwrite.com/v1/health/db is back UP
Total downtime: 12 minutes
Step 6: Docker Compose health checks
If you manage Appwrite via Docker Compose (the standard self-hosted setup), add container-level health checks to the core service:
# docker-compose.yml (add to the appwrite service)
services:
appwrite:
# ... existing config ...
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/v1/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 90s
This makes Docker aware of Appwrite's health state and restarts the container automatically on repeated failures. Vigilmon handles the external alert; Docker handles the self-healing.
Step 7: Set up a public status page
If you're offering Appwrite as a backend to other developers or teams, give them visibility into service health.
In Vigilmon:
- Status Pages → New Status Page
- Name it (e.g. "Backend Services")
- Add monitors grouped by service:
- API — the core
/v1/healthmonitor - Database — the
/v1/health/dbmonitor - Storage — the
/v1/health/storage/localmonitor
- API — the core
- Save and share the public URL
What you've built
| What | How |
|---|---|
| API health monitoring | Vigilmon HTTP monitor on /v1/health |
| Per-service health | Separate monitors for DB, cache, queue, storage |
| Keyword assertion | Verify "status":"pass" in response body |
| Cloud function monitoring | Heartbeat ping after each successful execution |
| Console monitoring | HTTP monitor on the Appwrite console URL |
| Instant alerts | Slack/webhook notifications on down + recovery |
| Container self-healing | Docker Compose healthcheck + restart policy |
| Public status page | Vigilmon status page for API consumers |
Appwrite's built-in /v1/health API does most of the heavy lifting. The key is checking each service independently — a database failure that keeps the API process alive is invisible to a single top-level monitor but immediately visible when you watch /v1/health/db separately.
Get started free at vigilmon.online — your first monitor is running in under a minute.