Health API
TBMQ exposes health checks through the Spring Boot Actuator framework.
Health checks let monitoring systems assess the state of TBMQ and its dependencies, and alerting can be configured based on the reported status.
The primary endpoint is /actuator/health on the HTTP port (HTTP_BIND_PORT, default 8083 — the same port that
serves the web UI and REST API), and it can be configured to include detailed status for PostgreSQL, Kafka,
Redis, and the broker’s own MQTT listeners.
Response status codes
Section titled “Response status codes”| HTTP status | Meaning |
|---|---|
200 OK |
All components are healthy. |
503 Service Unavailable |
One or more components have failed. |
Configuration
Section titled “Configuration”The parameters below control what the health endpoint exposes and which Actuator endpoints are reachable over HTTP.
management: health: diskspace: # Enable/disable disk space health check enabled: "${HEALTH_DISKSPACE_ENABLED:false}" endpoint: health: # Controls whether health endpoint shows full component details. # Options: # never — always hide details (default when security is enabled) # when-authorized — show details only to authenticated users # always — always include full health details in the response show-details: "${HEALTH_SHOW_DETAILS:never}" endpoints: web: exposure: # Actuator endpoints exposed via HTTP. # Add 'prometheus' to enable metrics scraping (e.g., 'health,info,prometheus') include: "${METRICS_ENDPOINTS_EXPOSE:health,info,prometheus}"health.diskspace.enabled — enables the disk space health check. It is disabled by default.
When enabled, TBMQ reports low disk space on the container. The threshold is not surfaced in TBMQ’s configuration
file, so Spring Boot’s default of 10 MB free space applies — treat the check as a disk-full signal rather than an
early warning.
endpoint.health.show-details — controls the visibility of component-level details in the response.
It defaults to never, so out of the box /actuator/health returns only the aggregate {"status":"UP"} — enough for a
liveness probe, but not enough to tell which dependency is down. Set it to always to include the per-component
breakdown shown below.
endpoints.web.exposure.include — comma-separated list of Actuator endpoints exposed over HTTP.
The default health,info,prometheus also serves /actuator/prometheus for metrics scraping and /actuator/info.
Remove prometheus if you do not scrape metrics from this port. Keep health in the list — an endpoint that is not
named there is not exposed, and /actuator/health then returns 404.
Health endpoint responses
Section titled “Health endpoint responses”The /actuator/health endpoint returns JSON with the overall system status.
When show-details is not never, the response also includes the status of each component.
Healthy response:
{ "status": "UP", "components": { "db": { "status": "UP", "details": { "database": "PostgreSQL", "validationQuery": "isValid()" } }, "kafka": { "status": "UP", "details": { "brokerCount": 3 } }, "ping": { "status": "UP" }, "redis": { "status": "UP", "details": { "version": "7.0.15" } }, "tbmq": { "status": "UP" } }}Unhealthy response:
{ "status": "DOWN", "components": { "db": { "status": "UP", "details": { "database": "PostgreSQL", "validationQuery": "isValid()" } }, "kafka": { "status": "UP", "details": { "brokerCount": 3 } }, "ping": { "status": "UP" }, "redis": { "status": "DOWN", "details": { "error": "org.springframework.dao.QueryTimeoutException: Redis command timed out" } }, "tbmq": { "status": "UP" } }}When all components are UP, all dependencies are healthy and TBMQ is running normally.
When a component fails, its status changes to DOWN and the response includes an error message describing the failure, like a Redis connection timeout or an unreachable Kafka broker.
If any component reports DOWN, the overall status becomes DOWN and the HTTP response code changes to 503.
What each component checks
Section titled “What each component checks”| Component | Check | Notes |
|---|---|---|
tbmq |
Every enabled MQTT listener’s server channel is open and active | TBMQ’s own indicator. Covers the TCP, TLS, WS, and WSS listeners; a listener that is disabled by configuration counts as healthy. This is what tells you the broker is actually accepting MQTT connections, not merely serving HTTP. |
kafka |
Kafka Admin API describeCluster succeeds; reports brokerCount |
TBMQ’s own indicator. The request goes to a single broker, and brokerCount is the number of brokers that broker reports as cluster members — so the check is UP as soon as any one broker is reachable. It does not validate replication, partition health, or per-topic state. Alert on brokerCount dropping below your expected node count separately. |
redis |
Redis responds to the connectivity check; reports the server version |
Fails on command timeout — see Timeout configuration. |
db |
PostgreSQL connection validated via isValid() |
Standard Spring Boot datasource indicator. |
ping |
Always UP |
Spring Boot’s trivial liveness indicator; carries no TBMQ-specific meaning. |
diskSpace |
Free space above the threshold | Present only when HEALTH_DISKSPACE_ENABLED=true. |
Timeout configuration
Section titled “Timeout configuration”Health checks verify connectivity to Kafka, Redis, and PostgreSQL by executing commands against each service. Each command has a configurable timeout — if the command does not complete within that time, the connectivity check is considered failed.
queue: kafka: admin: # Kafka Admin client command timeout in seconds (describeCluster, listTopics, etc.) command-timeout: "${TB_KAFKA_ADMIN_COMMAND_TIMEOUT_SEC:30}"
lettuce: config: # Maximum time in seconds to wait for a Lettuce (Redis) command to complete. # This applies to health checks and all command execution (e.g., GET, SET, PING). # Reduce to fail fast when Redis is unresponsive. command-timeout: "${REDIS_LETTUCE_COMMAND_TIMEOUT_SEC:30}"
spring: datasource: hikari: # Maximum time in milliseconds HikariCP waits to acquire a connection from the pool. # If exceeded, an exception is thrown. connectionTimeout: "${SPRING_DATASOURCE_CONNECTION_TIMEOUT_MS:30000}"Integration Executor health check
Section titled “Integration Executor health check”The TBMQ Integration Executor (IE) exposes its own health check at /actuator/health on its HTTP port
(HTTP_BIND_PORT, default 8082 — the same variable name the broker uses, with a different default).
It monitors connectivity to Kafka only: the IE has no PostgreSQL or Redis connection, so no db or redis
component appears.
Healthy response:
{ "status": "UP", "components": { "kafka": { "status": "UP", "details": { "brokerCount": 3 } }, "ping": { "status": "UP" } }}Using health checks in container environments
Section titled “Using health checks in container environments”Docker Compose
Section titled “Docker Compose”healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8083/actuator/health"] interval: 30s retries: 3 start_period: 30s timeout: 10sKubernetes
Section titled “Kubernetes”The reference TBMQ manifests probe the MQTT port rather than the health endpoint, because a TCP check on 1883 proves the broker is accepting MQTT connections and does not restart the pod when a shared dependency such as Kafka or Redis has a hiccup:
readinessProbe: tcpSocket: port: 1883 initialDelaySeconds: 30 periodSeconds: 20 timeoutSeconds: 10 successThreshold: 1 failureThreshold: 5
livenessProbe: tcpSocket: port: 1883 initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 10 successThreshold: 1 failureThreshold: 10Use /actuator/health for readiness when you want a node to be pulled out of the load balancer while its
dependencies are unreachable:
readinessProbe: httpGet: path: /actuator/health port: 8083 initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 10 failureThreshold: 3For details, see the Docker health check documentation and Kubernetes probes documentation.
Was this helpful?