Monitoring
Health endpoints, log levels, Docker health checks, and alerting for WaSphere.
Monitoring
WaSphere exposes health endpoints, structured JSON logs, and Docker health checks to integrate with your existing monitoring stack. This page covers built-in observability tools and how to set up alerting.
Health Endpoints
Dashboard API — /api/health
curl https://wa.yourdomain.com/api/health
{
"status": "ok",
"version": "1.4.2",
"uptime": 86400,
"database": {
"status": "connected",
"latencyMs": 2
},
"redis": {
"status": "connected",
"latencyMs": 1
},
"waServer": {
"status": "reachable",
"latencyMs": 8,
"activeSessions": 3
},
"queues": {
"messageQueue": { "waiting": 0, "active": 1, "failed": 0 },
"webhookQueue": { "waiting": 2, "active": 0, "failed": 0 }
},
"timestamp": "2026-05-25T10:00:00.000Z"
}
Status values:
ok— all systems nominaldegraded— one or more non-critical subsystems are unhealthy (e.g. wa-server temporarily unreachable but reconnecting)error— critical subsystem down (database or redis unreachable)
The HTTP status code mirrors the health state:
200—okordegraded503—error
WA Server — /health
Accessible internally only (port 3001):
docker compose exec wa-server wget -qO- http://localhost:3001/health
{
"status": "ok",
"activeSessions": 3,
"sessions": [
{ "id": "sess_abc123", "name": "support", "status": "connected", "phoneNumber": "+447700900123" },
{ "id": "sess_def456", "name": "sales", "status": "connected", "phoneNumber": "+447700900456" },
{ "id": "sess_ghi789", "name": "notifications", "status": "reconnecting" }
],
"uptime": 86400,
"memoryMb": 245
}
Session Status API
Get live status for all sessions via the main API:
curl https://wa.yourdomain.com/api/sessions \
-H "X-API-Key: YOUR_API_KEY"
Filter by status:
curl "https://wa.yourdomain.com/api/sessions?status=disconnected" \
-H "X-API-Key: YOUR_API_KEY"
Docker Health Checks
The docker-compose.yml configures health checks for all services. View current health:
docker compose ps
docker inspect --format='{{.Name}}: {{.State.Health.Status}}' $(docker compose ps -q)
Example output:
/wasphere-traefik-1: healthy
/wasphere-postgres-1: healthy
/wasphere-redis-1: healthy
/wasphere-wa-server-1: healthy
/wasphere-dashboard-api-1: healthy
Health check configuration (reference)
# From docker-compose.yml
services:
dashboard-api:
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
wa-server:
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3001/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
postgres:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U wasphere -d wasphere"]
interval: 10s
timeout: 5s
retries: 5
redis:
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
Log Management
Log format
All WaSphere services output structured JSON logs to stdout:
{
"level": "info",
"message": "Message sent successfully",
"sessionId": "sess_abc123",
"messageId": "3EB0C767D097B7C7A5C1",
"to": "447700900456",
"durationMs": 145,
"timestamp": "2026-05-25T10:00:00.000Z"
}
Log levels
Set LOG_LEVEL in .env to control verbosity:
| Level | When to use |
|---|---|
error | Production — only errors and critical failures |
warn | Production — errors plus warnings (reconnects, retries) |
info | Default — normal operational events |
debug | Diagnosing issues — includes request/response details |
verbose | Deep debugging — includes Baileys internal events |
debug and verbose logs include message content. Avoid these levels in production to prevent sensitive data (phone numbers, message text) from appearing in log aggregation systems.
Viewing logs
# All services
docker compose logs -f
# Specific service, last 100 lines
docker compose logs wa-server --tail=100 -f
# Filter for errors only (requires jq)
docker compose logs dashboard-api -f | jq 'select(.level == "error")'
# Search for a specific session
docker compose logs wa-server -f | grep "sess_abc123"
Shipping logs to a log aggregator
Add the Loki Docker logging driver to docker-compose.yml:
services:
dashboard-api:
logging:
driver: loki
options:
loki-url: "http://loki:3100/loki/api/v1/push"
loki-batch-size: "400"
labels: "service,version"Install the Loki Docker plugin:
docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissionsservices:
dashboard-api:
logging:
driver: "json-file"
options:
max-size: "10m"
labels:
com.datadoghq.ad.logs: '[{"source": "nodejs", "service": "wasphere-api"}]'Install the Datadog Agent container alongside the stack:
datadog:
image: gcr.io/datadoghq/agent:7
environment:
DD_API_KEY: ${DD_API_KEY}
DD_LOGS_ENABLED: "true"
DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL: "true"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /proc/:/host/proc/:roservices:
dashboard-api:
logging:
driver: syslog
options:
syslog-address: "udp://logs.papertrailapp.com:PORT"
tag: "wasphere-api"Uptime Monitoring
Use an external uptime monitor (Better Uptime, UptimeRobot, Freshping, etc.) to alert you when the health endpoint goes down.
Endpoint to monitor: https://wa.yourdomain.com/api/health
Expected HTTP status: 200
Check interval: 1–5 minutes
Alert threshold: 2 consecutive failures (avoids false positives from brief blips)
Example: UptimeRobot configuration
- Create a new monitor — HTTPS type
- URL:
https://wa.yourdomain.com/api/health - Monitoring interval: 5 minutes
- Alert contacts: your email/Slack
- Keyword check:
"status":"ok"(string match in response body for deeper health validation)
Alerting on Session Disconnects
Beyond infrastructure monitoring, you'll want alerts when a WhatsApp session drops. Use WaSphere webhooks for this:
// Express.js webhook handler — alert on session disconnect
app.post('/webhooks/wasphere', verifySignature, (req, res) => {
res.json({ received: true });
const { event, data } = req.body;
if (event === 'session.disconnected') {
const { sessionName, reason } = data;
// Send alert via your preferred channel
sendSlackAlert({
text: `WhatsApp session disconnected`,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `*Session:* ${sessionName}\n*Reason:* ${reason}\n*Action needed:* Check the WaSphere dashboard`
}
}
]
});
// Or send an email
sendEmail({
to: 'ops@yourcompany.com',
subject: `WaSphere Alert: Session "${sessionName}" disconnected`,
body: `Reason: ${reason}. Please check: https://wa.yourdomain.com`,
});
}
});
See Webhooks for the full event list and payload schemas.
Resource Monitoring
View container resource usage
# Live stats for all WaSphere containers
docker stats $(docker compose ps -q)
Example output:
CONTAINER CPU % MEM USAGE / LIMIT NET I/O BLOCK I/O
wasphere-wa-server 0.8% 312MiB / 2GiB 1.2GB / 450MB 0B / 0B
wasphere-api 0.3% 178MiB / 2GiB 890MB / 1.1GB 0B / 0B
wasphere-postgres 0.1% 89MiB / 2GiB 230MB / 180MB 45GB / 12GB
wasphere-redis 0.0% 28MiB / 2GiB 1.1GB / 980MB 0B / 0B
Resource limits in docker-compose.yml
Prevent any single service from consuming all server resources:
services:
wa-server:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
memory: 256M
dashboard-api:
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
Memory limits trigger container restarts if exceeded. Set limits with headroom — if WA Server uses 300 MB with 3 sessions, don't set the limit to 320 MB. Add sessions gradually and monitor before tightening limits.
BullMQ Queue Monitoring
The Dashboard API uses BullMQ for message dispatch and webhook delivery. Monitor queue health:
# Check queue depths via the API
curl https://wa.yourdomain.com/api/health | jq .queues
A growing failed count in webhookQueue means your webhook endpoint is returning errors — check the delivery log in the dashboard.
A growing waiting count in messageQueue means messages are queuing up faster than they're being sent — usually caused by the per-session rate limit or a disconnected session.
Bull Board (optional)
The Dashboard API includes Bull Board at /api/admin/queues (admin JWT required). It provides a web UI to inspect, retry, and delete queue jobs.
https://wa.yourdomain.com/api/admin/queues
Maintenance Mode
To put WaSphere into maintenance (reject API requests while keeping sessions connected):
# Enable maintenance mode
curl -X POST https://wa.yourdomain.com/api/admin/maintenance \
-H "Authorization: Bearer ADMIN_JWT" \
-d '{"enabled": true, "message": "Scheduled maintenance until 14:00 UTC"}'
# The API returns 503 with the maintenance message to all non-admin requests
# Disable maintenance mode
curl -X POST https://wa.yourdomain.com/api/admin/maintenance \
-H "Authorization: Bearer ADMIN_JWT" \
-d '{"enabled": false}'