Skip to main content

Health API

Check the overall health of the InfoConnect Hybrid Search Engine.

Endpoint​

GET /health

Request​

No authentication required for health checks.

Response​

Healthy​

{
"status": "healthy",
"version": "0.5.15",
"components": {
"api": "ok",
"redis": "ok",
"qdrant": "ok",
"celery": "ok",
"publication": "ok"
},
"publishing": {
"status": "ready",
"reason": null,
"authority_mode": "READY"
},
"diagnostics": {
"publication": {
"status": "ready",
"serving_status": "ready",
"publishing_status": "ready",
"authority_mode": "READY"
}
}
}

Safe publication fencing​

Publication writes pause while the deployment-wide fence is active, but the last ready snapshot remains safe for reads. The endpoint stays HTTP 200 and top-level status stays healthy when all serving components are healthy:

{
"status": "healthy",
"version": "0.5.15",
"components": {
"api": "ok",
"redis": "ok",
"qdrant": "ok",
"celery": "ok",
"publication": "ok"
},
"publishing": {
"status": "degraded",
"reason": "fencing",
"authority_mode": "FENCING"
},
"diagnostics": {
"publication": {
"status": "ready",
"serving_status": "ready",
"publishing_status": "degraded",
"authority_mode": "FENCING"
}
}
}

Degraded dependency​

{
"status": "degraded",
"version": "0.5.15",
"components": {
"api": "ok",
"redis": "error",
"qdrant": "ok",
"celery": "ok",
"publication": "ok"
},
"publishing": {
"status": "ready",
"reason": null,
"authority_mode": "READY"
}
}

Version Field​

The top-level version field is the Product Version of the running service. It is derived from the package version in pyproject.toml, not from a separately edited health-check constant. Use it to confirm which release is actually serving traffic after a deploy, rollback, or local rebuild.

The same Product Version also appears as info.version in /openapi.json. Run just version-check before release work to verify that pyproject.toml, runtime metadata, app.version, /health, and the committed OpenAPI document agree.

Component Status​

ComponentDescription
apiFastAPI application status
redisApplication-state Redis connection
qdrantQdrant vector database connection
celeryAlways ok. Kept for response compatibility; /health does not probe Celery workers. Watch worker backlog through /metrics infoconnect_queue_depth and just status
publicationPublication-backed read-serving safety (only when PUBLICATION_ENABLED=true)
modernbert-onnxModernBERT ONNX classification model health (when CLASSIFICATION_ENABLED=true; omitted when classification is off)

Publication-enabled responses include two distinct typed signals:

  • components.publication and top-level status describe whether this API process can safely serve publication-backed reads. READY and FENCING are serving-safe only while the local request gate is valid and the worker safe-serving deadline is live.
  • publishing describes immediate write admission. It is ready in READY, degraded with reason fencing in serving-safe FENCING, and unavailable in RECOVERING, MAINTENANCE, when authority data is unreadable or missing, when the local gate is invalidated, or when the worker deadline expires.

Generation cleanup does not enter MAINTENANCE; see the cleanup contract.

When publication is disabled, publishing is still present with status: "ready", reason: null, and authority_mode: "DISABLED"; the publication component and diagnostics are omitted.

diagnostics.publication exposes typed serving_status, publishing_status, and authority_mode values plus bounded authority, Redis, Qdrant, collection-schema, and recovery-evidence identifiers. Publication readiness and diagnostic reads each have a two-second deadline. The Qdrant version and collection-schema digest come from a cached read with a five-minute maximum age. In-process lane or index provisioning invalidates the cache even if provisioning only partially succeeds. The next probe after invalidation or expiry re-reads the four publication lane schemas; no background refresh runs. A probe racing provisioning can cache the earlier schema until expiry. Backup and restore compatibility checks use a fresh, uncached read.

Serving failures fail closed immediately. Any state other than READY or serving-safe FENCING sets components.publication to error and returns HTTP 503 on the first sample. This includes RECOVERING, MAINTENANCE, unreadable or missing authority, invalidated gates, expired worker deadlines, and probe timeouts. Serving-safe FENCING also keeps HTTP 200; its separate publishing signal remains degraded.

Examples​

Basic Health Check​

curl http://localhost:8000/health

Monitoring Script​

#!/bin/bash

response=$(curl -s http://localhost:8000/health)
status=$(echo "$response" | jq -r '.status')
version=$(echo "$response" | jq -r '.version')

if [ "$status" = "healthy" ]; then
echo "✅ System is healthy (version $version)"
exit 0
else
echo "❌ System is degraded (version $version)"
echo "$response" | jq '.'
exit 1
fi

Docker Health Check​

Use the healthcheck in docker-compose.prod.yml for production; see Production container healthcheck for its detection bound and startup grace period. The base docker-compose.yml retains its development/QA probe cadence.

Kubernetes Liveness Probe​

livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
periodSeconds: 30

readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10

Load Balancer Health Check​

Configure your load balancer to ping /health every 30 seconds. Publication serving failures return 503 and remove the instance from rotation through ordinary HTTP health checks. A safe publication fence returns 200: reads continue from pinned snapshots while publishing.status="degraded" identifies paused write activation. Other component failures return a degraded body with HTTP 200; use a body-aware monitor if those failures should also remove an instance.

Response Codes​

CodeStatusDescription
200Healthy or degradedRead serving is safe; inspect publishing, status, and components for paused publication writes or other dependency failures
503DegradedPublication is enabled and read serving is unsafe; the first unsafe sample fails closed

Use top-level status and components.publication for serving availability. Alert independently on publishing.status: safe FENCING intentionally keeps the instance in rotation while new activation waits. A publication 503 remains fail-closed when no safe pinned view can be served.

Troubleshooting​

Redis Error​

{
"status": "degraded",
"components": {
"redis": "error"
}
}

Check: Redis container is running

docker compose ps redis
docker compose logs redis

Qdrant Error​

{
"status": "degraded",
"components": {
"qdrant": "error"
}
}

Check: Qdrant container is running

docker compose ps qdrant
curl http://localhost:6333/healthz

Celery workers​

components.celery is always ok; /health does not check workers. To see whether workers are draining work, check queue depth and worker processes:

curl -s http://localhost:8000/metrics | grep infoconnect_queue_depth
just status

Production container healthcheck​

The production API container probes /health every 60 seconds with a 10-second timeout and 2 retries, so a dead API is marked unhealthy within 140 seconds (retries × (interval + timeout)) of its last good probe after startup grace has ended. During the first 10 minutes after start (start_period), the container probes every 10 seconds and failures do not count until a probe succeeds, because publication recovery and model loading keep :8000 closed for several minutes. The startup probe interval requires Docker Engine 25 or newer. unhealthy does not restart the container; route it to your monitor. Production deployment waits by requesting /health directly; no Compose service depends on API container health. See docker-compose.prod.yml.

Best Practices​

  1. Monitor continuously - Use /health for uptime monitoring
  2. Alert on degraded - Set up alerts when status != healthy
  3. Check components - Inspect individual component status for debugging
  4. Log responses - Log health check results for troubleshooting