How the Health Checker Verifies Memgraph and Qdrant Connections in code-graph-rag
The HealthChecker class in codebase_rag/tools/health_checker.py orchestrates TCP and HTTP health checks to confirm Memgraph and Qdrant are reachable before the RAG pipeline starts.
This article explains how the vitali87/code-graph-rag repository validates external service dependencies at runtime. The health checker implementation ensures that both the Memgraph graph database and Qdrant vector store are operational before queries are processed, preventing failures downstream in the retrieval-augmented generation (RAG) workflow.
Architecture of the Health Checking System
The health verification system consists of three coordinated components: a reusable checker utility, service-specific validation functions, and a stack manager that orchestrates startup.
Core Components
| Component | Purpose | Implementation Location |
|---|---|---|
HealthChecker class |
Registry and executor for health checks | codebase_rag/tools/health_checker.py |
add_check(name, fn) |
Registers a named check function | codebase_rag/tools/health_checker.py |
run_all_checks() |
Executes all registered checks sequentially | codebase_rag/tools/health_checker.py |
wait_for_memgraph() |
TCP/Bolt handshake validation for Memgraph | codebase_rag/stack/health.py |
wait_for_qdrant() |
HTTP GET validation for Qdrant REST API | codebase_rag/stack/health.py |
wait_healthy() |
Orchestrates blocking startup verification | codebase_rag/stack/manager.py |
The flow proceeds as follows:
- The stack manager instantiates
HealthChecker - It registers
wait_for_memgraphandwait_for_qdrantas named checks run_all_checks()executes with retry logic until both succeed or timeout- Startup aborts if any check fails, ensuring no operations against unavailable services
How Memgraph Connection Verification Works
The wait_for_memgraph(host, port, timeout) function in [codebase_rag/stack/health.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/stack/health.py#L12-L30) validates the graph database through TCP socket connection followed by the Bolt protocol handshake.
from codebase_rag.stack.health import wait_for_memgraph
# Verify Memgraph is accepting connections on default Bolt port 7687
is_healthy = wait_for_memgraph(
host="localhost",
port=7687,
timeout=30.0 # seconds
)
The implementation attempts to:
- Open a TCP socket to the specified
host:port - Perform the Memgraph Bolt protocol handshake using the Python driver
- Return
Trueupon successful handshake,Falseif timeout expires
This confirms Memgraph is not merely listening on the port but actually ready to process Cypher queries.
How Qdrant Connection Verification Works
The wait_for_qdrant(host, port, timeout) function in [codebase_rag/stack/health.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/stack/health.py#L31-L48) validates the vector store through HTTP health endpoint polling.
from codebase_rag.stack.health import wait_for_qdrant
# Verify Qdrant REST API is responsive on default port 6333
is_healthy = wait_for_qdrant(
host="localhost",
port=6333,
timeout=30.0 # seconds
)
The implementation:
- Sends HTTP
GETrequest tohttp://{host}:{port}/ - Expects HTTP 200 response indicating the REST API is operational
- Retries with exponential backoff until success or timeout
This lightweight check confirms Qdrant's vector search capabilities are available without requiring actual query execution.
Using HealthChecker Directly
For custom integrations, instantiate HealthChecker and register checks explicitly as shown in [codebase_rag/tools/health_checker.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/tools/health_checker.py):
from codebase_rag.tools.health_checker import HealthChecker
from codebase_rag.stack.health import wait_for_memgraph, wait_for_qdrant
checker = HealthChecker()
# Register checks with descriptive names
checker.add_check(
"memgraph",
lambda: wait_for_memgraph("memgraph", 7687, timeout=30)
)
checker.add_check(
"qdrant",
lambda: wait_for_qdrant("qdrant", 6333, timeout=30)
)
# Execute all checks
healthy, details = checker.run_all_checks()
print(f"All services healthy: {healthy}")
print(f"Results: {details}") # {'memgraph': True, 'qdrant': True}
The run_all_checks() method returns:
healthy: Boolean indicating if all checks passeddetails: Dictionary mapping check names to their boolean results
Integrated Startup Sequence
The default behavior uses StackManager in [codebase_rag/stack/manager.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/stack/manager.py#L13-L27), which internally calls wait_healthy():
from codebase_rag.stack.manager import StackManager
# Blocks until both Memgraph and Qdrant are verified healthy
stack = StackManager()
stack.start() # Raises exception if health checks fail within timeout
The manager handles:
- Retry logic: Exponential backoff between check attempts
- Timeout enforcement: Hard limit on total startup wait time
- Diagnostic logging: Records duration and failure reasons per service
- Graceful failure: Raises descriptive exception identifying which service failed
Configuration and Timeout Behavior
Both check functions accept configurable parameters:
| Parameter | Default | Description |
|---|---|---|
host |
"localhost" |
Service hostname or IP address |
port |
7687 (Memgraph), 6333 (Qdrant) |
Service port number |
timeout |
30.0 |
Maximum seconds to wait for service readiness |
Adjust these when deploying with container orchestration or non-standard ports:
# Docker Compose service names as hosts
checker.add_check("memgraph",
lambda: wait_for_memgraph("memgraph-db", 7687, timeout=60))
checker.add_check("qdrant",
lambda: wait_for_qdrant("qdrant-server", 6333, timeout=60))
Summary
HealthCheckerprovides a reusable registry pattern for service health validation incodebase_rag/tools/health_checker.pywait_for_memgraphverifies Bolt protocol connectivity to confirm Memgraph query readinesswait_for_qdrantpolls the HTTP REST endpoint to confirm Qdrant vector search availabilityStackManagerorchestrates blocking startup verification, ensuring the RAG pipeline only proceeds when dependencies are confirmed healthy- All checks are idempotent, retry-safe, and include diagnostic timing for observability
Frequently Asked Questions
How does the health checker handle transient network failures?
The wait_for_memgraph and wait_for_qdrant functions implement retry loops with exponential backoff. Each attempt is timed and logged, allowing the caller to specify a total timeout budget. As implemented in codebase_rag/stack/health.py, checks continue retrying until success or timeout expiration, making them resilient to container startup delays and network blips.
Can custom health checks be added beyond Memgraph and Qdrant?
Yes. The HealthChecker.add_check(name, fn) method accepts any callable returning a boolean. You can register additional checks for services like Redis, Elasticsearch, or custom APIs. The run_all_checks() method executes all registered checks sequentially and aggregates results, as defined in codebase_rag/tools/health_checker.py.
What happens if a health check fails during StackManager.start()?
The wait_healthy() method in codebase_rag/stack/manager.py raises a runtime exception identifying the failing service and the accumulated error details. This prevents the application from starting in a degraded state. The exception message includes which specific check failed (Memgraph or Qdrant) and the final error encountered during the timeout period.
Are there unit tests for the health checker implementation?
Yes. The test suite in codebase_rag/tests/test_health_checker.py validates the HealthChecker class behavior, including successful check registration, proper result aggregation, and timeout handling. These tests ensure the health verification logic remains reliable across code changes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →