Valkey is the Linux Foundation's open-source continuation of Redis, fully compatible with existing Redis clients and commands while remaining free from proprietary licensing constraints. As Valkey adoption accelerates across self-hosted infrastructure, the operational reality is familiar: a cache stampede, an OOM kill, or a replication split-brain can silently drop your Valkey instance while your application hammers the primary database with every cache miss.
Vigilmon gives you external visibility into Valkey availability through HTTP probe monitoring and heartbeat monitoring for Valkey-dependent background workers. This tutorial walks through setting up both.
Why Valkey Monitoring Matters
Valkey is often the single point of failure between your application and your database. Internal process monitoring (systemd, Docker health checks) tells you whether the Valkey process is running — but it cannot tell you:
- Whether Valkey is reachable from your application servers across the network
- Whether Valkey has hit its
maxmemorylimit and is silently refusing writes undernoevictionpolicy - Whether a replica has fallen behind and is serving stale data to read-heavy workloads
- Whether your Valkey-dependent background workers have stopped processing jobs
- Whether a cluster partition has left your application writing to a minority shard
These failure modes all pass process-level checks while causing real user impact. External monitoring through Vigilmon catches them by testing the actual path your application uses to reach Valkey.
Step 1: Build a Valkey Health Endpoint
Valkey does not expose an HTTP health endpoint natively. You need a thin wrapper in your application layer that checks Valkey and returns HTTP 200 or 503.
Node.js Example
// health/valkey.js — Valkey health endpoint for Express
const express = require('express');
const { createClient } = require('redis'); // Valkey is fully Redis-client compatible
const app = express();
const client = createClient({ url: process.env.VALKEY_URL || 'redis://localhost:6379' });
client.connect().catch(console.error);
app.get('/health/valkey', async (req, res) => {
try {
// PING verifies the connection is alive
const pong = await client.ping();
if (pong !== 'PONG') throw new Error('Unexpected PING response');
// Check memory pressure — alert if over 90% of maxmemory
const info = await client.info('memory');
const usedMatch = info.match(/used_memory:(\d+)/);
const maxMatch = info.match(/maxmemory:(\d+)/);
const used = usedMatch ? parseInt(usedMatch[1]) : 0;
const max = maxMatch ? parseInt(maxMatch[1]) : 0;
const memPressure = max > 0 ? used / max : 0;
if (memPressure > 0.90) {
return res.status(503).json({
status: 'critical',
reason: 'memory_pressure',
used_bytes: used,
max_bytes: max,
});
}
return res.status(200).json({ status: 'ok', pong });
} catch (err) {
return res.status(503).json({ status: 'down', error: err.message });
}
});
app.listen(3001);
Python (FastAPI) Example
# health/valkey.py — Valkey health endpoint for FastAPI
import os
import redis
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
r = redis.Redis.from_url(
os.environ.get("VALKEY_URL", "redis://localhost:6379"),
decode_responses=True,
)
@app.get("/health/valkey")
def valkey_health():
try:
pong = r.ping()
info = r.info("memory")
used = info.get("used_memory", 0)
max_mem = info.get("maxmemory", 0)
if max_mem > 0 and used / max_mem > 0.90:
return JSONResponse(status_code=503, content={
"status": "critical",
"reason": "memory_pressure",
"used_bytes": used,
"max_bytes": max_mem,
})
return {"status": "ok", "pong": pong}
except Exception as e:
return JSONResponse(status_code=503, content={
"status": "down",
"error": str(e),
})
Deploy this endpoint alongside your Valkey client. Verify it manually before wiring up Vigilmon:
curl -i https://your-app.example.com/health/valkey
# HTTP/1.1 200 OK
# {"status":"ok","pong":"PONG"}
Step 2: Configure a Vigilmon HTTP Monitor for Valkey
- Log in to vigilmon.online and go to Monitors → New Monitor
- Choose HTTP / HTTPS
- Set the URL to your Valkey health endpoint:
https://your-app.example.com/health/valkey - Set the check interval to 1 minute
- Under Expected response, configure:
- Status code:
200 - Response body contains:
"status":"ok" - Response time threshold:
1000ms
- Status code:
- Under Alert channels, assign your Slack or email channel
- Save the monitor
Vigilmon probes from multiple geographic regions simultaneously. A single transient probe failure won't page you — Vigilmon requires multi-region consensus before opening an incident, so you get confident, actionable alerts rather than alert fatigue.
What This Catches
| Failure | systemd / Docker | Vigilmon |
|---|---|---|
| Valkey process crash | ✓ | ✓ |
| Network partition to Valkey | ✗ | ✓ |
| Memory pressure (noeviction mode) | ✗ | ✓ |
| Wrong VALKEY_URL in app config | ✗ | ✓ |
| TLS certificate expiry on Valkey TLS port | ✗ | ✓ |
Step 3: Heartbeat Monitoring for Valkey-Dependent Workers
Background workers that consume from Valkey-backed queues (BullMQ, Celery, Sidekiq, RQ) will stop silently when Valkey goes down — the worker blocks waiting for a connection and never processes another job. No error is thrown; the queue just freezes.
Vigilmon's heartbeat monitors detect silent worker death: your worker pings Vigilmon after each successful processing cycle. If the ping stops arriving, Vigilmon fires an alert.
Set Up the Heartbeat Monitor
- In Vigilmon, go to Monitors → New Monitor → Heartbeat
- Set the name:
valkey-queue-worker - Set the expected interval: 5 minutes (adjust to your job frequency)
- Set the grace period: 10 minutes
- Save — copy the unique heartbeat URL, e.g.
https://vigilmon.online/heartbeat/abc123xyz
Wire It Into Your Worker
Node.js / BullMQ:
import { Worker } from 'bullmq';
import axios from 'axios';
const worker = new Worker('my-queue', async (job) => {
await processJob(job);
}, { connection: { host: 'localhost', port: 6379 } });
worker.on('completed', async () => {
await axios.get(process.env.VIGILMON_HEARTBEAT_URL).catch(() => {});
});
Python / RQ with Valkey backend:
from rq import Worker, Queue
from redis import Redis
import requests, os
r = Redis.from_url(os.environ["VALKEY_URL"])
def after_job_execution(job, connection, result, *args, **kwargs):
try:
requests.get(os.environ["VIGILMON_HEARTBEAT_URL"], timeout=5)
except Exception:
pass # never let a heartbeat failure kill the worker
q = Queue(connection=r)
worker = Worker([q], connection=r)
worker.work()
Ruby / Sidekiq:
# config/initializers/vigilmon_heartbeat.rb
class ValkeyHeartbeat
include Sidekiq::ServerMiddleware
def call(_worker, _job, _queue)
yield
Net::HTTP.get(URI(ENV["VIGILMON_HEARTBEAT_URL"]))
rescue => e
Rails.logger.warn("Vigilmon heartbeat failed: #{e}")
end
end
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add ValkeyHeartbeat
end
end
Step 4: Monitoring Valkey Replication and Cluster Health
Valkey supports both standalone replication and cluster mode. Each topology needs dedicated monitoring.
Replication Health Endpoint
Expose replica sync status in your health endpoint:
app.get('/health/valkey/replication', async (req, res) => {
try {
const info = await client.info('replication');
const role = info.match(/role:(\w+)/)?.[1];
const masterLinkDown = info.includes('master_link_status:down');
const replicationLag = parseInt(info.match(/master_repl_offset:(\d+)/)?.[1] || '0');
if (role === 'slave' && masterLinkDown) {
return res.status(503).json({
status: 'degraded',
reason: 'replica_disconnected_from_primary',
role,
});
}
return res.status(200).json({ status: 'ok', role, replication_lag: replicationLag });
} catch (err) {
return res.status(503).json({ status: 'down', error: err.message });
}
});
Monitor Naming Convention
Use a consistent naming convention in Vigilmon so your team can identify nodes at a glance:
[valkey-primary] cache /health/valkey[valkey-replica-1] cache /health/valkey/replication[valkey-replica-2] cache /health/valkey/replication
Group all Valkey monitors under a single Status Page for a unified view of your cache layer.
Step 5: Alert Routing for Cache Outages
Valkey outages cascade quickly: Valkey drops → cache misses spike → application response times surge → database CPU climbs → cascading failure. You want to page your on-call engineer before the cascade reaches the database.
Configure alert routing in Vigilmon:
| Monitor | Alert Channel | Priority |
|---|---|---|
| Primary Valkey /health/valkey | Slack + PagerDuty | P1 |
| Replica replication /health/valkey/replication | Slack | P2 |
| Worker heartbeat | Slack + email | P2 |
Set response time thresholds as early warnings:
- Alert at
500msfor the Valkey health endpoint — a slow health response often signals memory pressure before OOM - Alert at
2000msfor application endpoints that depend on Valkey — latency spikes signal cache misses amplifying database load
Summary
Valkey failures are fast and catastrophic — don't wait for users to report them. Vigilmon gives you:
| Monitor Type | What It Covers |
|---|---|
| HTTP monitor on /health/valkey | Valkey process, connectivity, memory pressure |
| HTTP monitor on /health/valkey/replication | Replica sync status, disconnection |
| Heartbeat monitor | Background worker and queue liveness |
Get started free at vigilmon.online — your first Valkey monitor is running in under two minutes.