Deep Health Check — Complete Implementation Guide
In this tutorial, you will learn about Deep Health Check. We cover key concepts, practical examples, and best practices to help you master this topic.
Deep health checks verify that the service is not just running but functioning correctly by performing end-to-end operations like writing test data, validating responses, and measuring performance.
What You'll Learn
By the end of this tutorial, you will know how to implement deep health checks that verify database read/write operations, cache consistency, business logic correctness, and response performance.
Why It Matters
A service can pass basic and dependency checks but still be broken. Deep health checks catch logic errors, data corruption, and performance degradation that simpler checks miss.
Real-World Use
Durga Antivirus Pro's scanning API runs a deep health check that downloads a known test file, scans it, and verifies the result matches expectations. If the scan produces the wrong result, the service is marked unhealthy.
Deep Health Check Learning Path
flowchart LR
A[Dependency Health] --> B[Deep Health Check]
B --> C[Read/Write Test]
B --> D[Business Logic]
B --> E[Performance Check]
B --> F{You Are Here}
style F fill:#f90,color:#fff
Database Read/Write Health Check
Verify the database is fully functional by writing and reading a test record.
class DatabaseReadWriteCheck {
constructor(db) {
this.db = db;
this.testPrefix = "health_check_";
}
async check() {
const testId = `${this.testPrefix}${Date.now()}`;
const results = [];
try {
// Write
const writeStart = Date.now();
await this.db.query(
"INSERT INTO health_checks (id, created_at) VALUES ($1, NOW())",
[testId]
);
results.push({ operation: "write", latencyMs: Date.now() - writeStart });
// Read
const readStart = Date.now();
const readResult = await this.db.query(
"SELECT * FROM health_checks WHERE id = $1",
[testId]
);
results.push({ operation: "read", latencyMs: Date.now() - readStart });
// Cleanup
await this.db.query("DELETE FROM health_checks WHERE id = $1", [testId]);
const allSuccessful = results.every(r => r.latencyMs !== undefined);
return {
name: "database-deep",
healthy: allSuccessful,
operations: results,
totalLatencyMs: results.reduce((s, r) => s + r.latencyMs, 0)
};
} catch (err) {
return {
name: "database-deep",
healthy: false,
error: err.message,
operations: results
};
}
}
}
const { Pool } = require("pg");
const pool = new Pool({ connectionString: "postgresql://localhost/test" });
const deepDb = new DatabaseReadWriteCheck(pool);
deepDb.check().then(r => console.log("Deep DB:", r.healthy ? "ok" : "FAIL"));
Business Logic Verification
Test that critical business operations produce the expected results.
class BusinessLogicHealthCheck {
constructor(calculator) {
this.calculator = calculator;
}
async check() {
const tests = [
{ name: "calculate-total", fn: () => this.calculator.calculateTotal([10, 20, 30]), expected: 60 },
{ name: "apply-discount", fn: () => this.calculator.applyDiscount(100, 10), expected: 90 },
{ name: "validate-email", fn: () => this.calculator.validateEmail("test@example.com"), expected: true },
{ name: "validate-bad-email", fn: () => this.calculator.validateEmail("invalid"), expected: false }
];
const results = await Promise.all(tests.map(async (test) => {
try {
const actual = await test.fn();
const passed = actual === test.expected;
return { name: test.name, passed, actual, expected: test.expected };
} catch (err) {
return { name: test.name, passed: false, error: err.message };
}
}));
const allPassed = results.every(r => r.passed);
return {
name: "business-logic",
healthy: allPassed,
tests: results,
passedCount: results.filter(r => r.passed).length,
totalCount: results.length
};
}
}
const mockCalculator = {
calculateTotal: async (items) => items.reduce((s, i) => s + i, 0),
applyDiscount: async (price, percent) => price * (1 - percent / 100),
validateEmail: async (email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
};
const bizCheck = new BusinessLogicHealthCheck(mockCalculator);
bizCheck.check().then(r => {
console.log("Business logic:", r.healthy ? "ok" : "FAIL");
console.log(`Passed ${r.passedCount}/${r.totalCount} tests`);
});
// Business logic: ok
// Passed 4/4 tests
Performance Health Check
Verify that operations complete within acceptable time thresholds.
class PerformanceHealthCheck {
constructor(thresholds) {
this.thresholds = {
databaseQueryMs: 100,
cacheFetchMs: 20,
apiResponseMs: 500,
...thresholds
};
}
async checkPerformance(operation) {
const start = Date.now();
await operation();
return Date.now() - start;
}
async check() {
const checks = [];
// Database query performance
const dbLatency = await this.checkPerformance(async () => {
await new Promise(r => setTimeout(r, 30));
});
checks.push({
name: "database-performance",
passed: dbLatency <= this.thresholds.databaseQueryMs,
latencyMs: dbLatency,
thresholdMs: this.thresholds.databaseQueryMs
});
// Cache performance
const cacheLatency = await this.checkPerformance(async () => {
await new Promise(r => setTimeout(r, 10));
});
checks.push({
name: "cache-performance",
passed: cacheLatency <= this.thresholds.cacheFetchMs,
latencyMs: cacheLatency,
thresholdMs: this.thresholds.cacheFetchMs
});
const allPassed = checks.every(c => c.passed);
return {
name: "performance",
healthy: allPassed,
checks,
timestamp: new Date().toISOString()
};
}
}
const perfCheck = new PerformanceHealthCheck({
databaseQueryMs: 100,
cacheFetchMs: 20,
apiResponseMs: 500
});
perfCheck.check().then(r => {
console.log("Performance:", r.healthy ? "ok" : "degraded");
r.checks.forEach(c => {
console.log(` ${c.name}: ${c.latencyMs}ms (threshold: ${c.thresholdMs}ms) ${c.passed ? "ok" : "SLOW"}`);
});
});
// Performance: ok
// database-performance: 30ms (threshold: 100ms) ok
// cache-performance: 10ms (threshold: 20ms) ok
End-to-End API Flow Check
Simulate a complete user flow to verify the entire system works.
class EndToEndHealthCheck {
constructor(apiClient) {
this.client = apiClient;
}
async simulateUserFlow() {
const steps = [];
// Step 1: Create a resource
try {
const createRes = await this.client.post("/api/users", {
name: "health-test",
email: `health-${Date.now()}@test.com`
});
const userId = createRes.id;
steps.push({ step: "create-user", passed: true, userId });
// Step 2: Read the resource
const readRes = await this.client.get(`/api/users/${userId}`);
steps.push({ step: "read-user", passed: readRes.id === userId });
// Step 3: Update the resource
await this.client.patch(`/api/users/${userId}`, { name: "health-test-updated" });
steps.push({ step: "update-user", passed: true });
// Step 4: Delete the resource
await this.client.delete(`/api/users/${userId}`);
steps.push({ step: "delete-user", passed: true });
} catch (err) {
steps.push({ step: "e2e-flow", passed: false, error: err.message });
}
const allPassed = steps.every(s => s.passed);
return {
name: "end-to-end",
healthy: allPassed,
steps
};
}
}
const mockClient = {
store: {},
idCounter: 0,
async post(path, data) {
this.idCounter++;
const id = this.idCounter;
this.store[id] = { ...data, id };
return { id };
},
async get(path) {
const id = parseInt(path.split("/").pop());
return this.store[id] || null;
},
async patch(path, data) {
const id = parseInt(path.split("/").pop());
if (this.store[id]) Object.assign(this.store[id], data);
},
async delete(path) {
const id = parseInt(path.split("/").pop());
delete this.store[id];
}
};
const e2e = new EndToEndHealthCheck(mockClient);
e2e.simulateUserFlow().then(r => {
console.log("E2E flow:", r.healthy ? "ok" : "FAIL");
r.steps.forEach(s => console.log(` ${s.step}: ${s.passed ? "ok" : "FAIL"}`));
});
// E2E flow: ok
// create-user: ok
// read-user: ok
// update-user: ok
// delete-user: ok
Scheduling Deep Health Checks
Deep health checks are expensive. Run them on a schedule, not on every probe.
class ScheduledDeepHealthCheck {
constructor(checkFn, options = {}) {
this.checkFn = checkFn;
this.intervalMs = options.intervalMs || 60000;
this.lastResult = null;
this.lastRunTime = 0;
}
async getResult() {
const now = Date.now();
if (now - this.lastRunTime > this.intervalMs) {
console.log("Running scheduled deep health check");
this.lastResult = await this.checkFn();
this.lastRunTime = now;
}
return this.lastResult;
}
async forceRun() {
this.lastResult = await this.checkFn();
this.lastRunTime = Date.now();
return this.lastResult;
}
}
const scheduled = new ScheduledDeepHealthCheck(
async () => ({ healthy: true, checkedAt: new Date().toISOString() }),
{ intervalMs: 60000 }
);
scheduled.getResult().then(r => {
console.log("Scheduled check result:", r.healthy);
});
// Running scheduled deep health check
// Scheduled check result: true
Common Mistakes
Running deep checks on every probe -- Deep checks are expensive. Run them every 30-60 seconds, not every 5 seconds like basic checks.
Not cleaning up test data -- Deep checks that write test data must clean up afterward. Accumulated test data can affect production queries and storage.
Using deep check failures for liveness -- A deep check failure doesn't mean the Process needs restarting. Use deep checks for readiness, not liveness.
Not randomizing test data -- Using the same test ID every time creates cache hits that don't test real code paths. Randomize test data.
Making deep checks too deep -- A deep check that tests every feature is fragile and slow. Test critical paths only.
Practice Questions
What is the difference between a dependency check and a deep check? A dependency check verifies connectivity (can I reach the database?). A deep check verifies functionality (can I write and read data?).
Why should deep health checks include cleanup? To prevent test records from accumulating in production databases, affecting storage, queries, and data integrity.
How often should deep health checks run? Every 30-60 seconds. They're too expensive to run on every probe but should run frequently enough to detect issues promptly.
Challenge: Implement a deep health check that reports the latency of each operation and marks unhealthy if any operation exceeds a threshold.
class ThresholdBasedDeepCheck {
constructor(operations, maxLatencyMs = 1000) {
this.operations = operations;
this.maxLatencyMs = maxLatencyMs;
}
async run() {
const results = [];
let anySlow = false;
for (const op of this.operations) {
const start = Date.now();
try {
await op.fn();
const latency = Date.now() - start;
const slow = latency > this.maxLatencyMs;
if (slow) anySlow = true;
results.push({ name: op.name, passed: !slow, latencyMs: latency, thresholdMs: this.maxLatencyMs });
} catch (err) {
results.push({ name: op.name, passed: false, error: err.message });
anySlow = true;
}
}
return { healthy: !anySlow, operations: results };
}
}
const check = new ThresholdBasedDeepCheck([
{ name: "db-write", fn: async () => new Promise(r => setTimeout(r, 50)) },
{ name: "cache-read", fn: async () => new Promise(r => setTimeout(r, 10)) }
], 200);
check.run().then(r => console.log("Threshold check:", r.healthy));
// Threshold check: true
FAQ
Mini Project
Build a deep health check module that performs database read/write tests, verifies critical business logic, measures operation latency, and reports results with pass/fail status per operation.
class DeepHealthModule {
constructor() {
this.testers = [];
}
addTester(name, tester) {
this.testers.push({ name, run: tester });
}
async execute() {
const results = [];
for (const { name, run } of this.testers) {
try {
const result = await run();
results.push({ tester: name, ...result });
} catch (err) {
results.push({ tester: name, passed: false, error: err.message });
}
}
const allPassed = results.every(r => r.passed !== false);
return {
status: allPassed ? "healthy" : "unhealthy",
results,
timestamp: new Date().toISOString()
};
}
}
const module = new DeepHealthModule();
module.addTester("Database Read/Write", async () => ({ passed: true, latencyMs: 45 }));
module.addTester("Business Logic", async () => ({ passed: true, testsPassed: 4 }));
module.addTester("Performance", async () => ({ passed: true, maxLatencyMs: 89 }));
module.execute().then(r => console.log("Deep health:", r.status, "-", r.results.length, "tests"));
What's Next
Now that you understand deep health checks, implement a health check in Express.js. Then explore Django health check integration.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro