Production Monitoring Best Practices
Production deployments require monitoring beyond EMQX Dashboard. Dashboard shows the current broker state but cannot notify operators if the broker or host becomes unavailable. The monitoring guidance on this page helps you detect loss of service, loss of redundancy, and resource exhaustion early enough to act.
This guidance applies to production deployments of EMQX Enterprise. Treat the example thresholds as starting points and adjust them to your service-level objectives (SLOs), tested capacity, traffic patterns, and recovery time.
Design a Production Monitoring System
Follow these principles when designing your monitoring system:
Export EMQX metrics to an external monitoring system.
Prometheus Pull mode is recommended for comprehensive monitoring. Scrape every EMQX node directly, rather than through a load balancer, so that a failed or isolated node cannot be hidden by a healthy node. Monitor the Prometheus
upmetric for every target.Forward EMQX built-in alarms.
Configure EMQX built-in alarm thresholds for your environment and send alarm events to an external notification system by using a Webhook or system topic. Do not rely on an operator noticing an alarm in the Dashboard.
Run an end-to-end MQTT check from outside the cluster.
A synthetic client should connect through the same load balancer, TLS listener, and authentication path as production clients. The client should publish a uniquely identified message, receive it on a subscription, and measure the total latency. This check detects failures that broker metrics alone cannot detect.
Monitor the host or container platform.
EMQX does not replace operating system, Kubernetes, or cloud-provider monitoring. Collect CPU throttling, memory pressure, disk capacity and latency, file descriptor use, network errors, container restarts, and time synchronization status.
Collect logs centrally.
Send warning, error, and critical logs from every node to storage outside the EMQX cluster. Prefer JSON-formatted logs so that alert rules can match the structured
msg,node, and other context fields. Logs reveal some conditions that are not represented by a metric or built-in alarm.Keep monitoring independent of EMQX.
The monitoring and notification path must remain available when an EMQX node, availability zone, or the entire cluster is unavailable.
TIP
Collect metrics at a shorter interval than the required detection time. For example, with a 15-second scrape interval and an alert after 2 consecutive failures, you can normally detect an unreachable target in less than 1 minute without paging on a single missed scrape.
Establish SLOs, Capacity Baselines, and Alert Thresholds
Use the following process instead of copying fixed thresholds into production:
- Define the user-visible SLOs for connection success, publish-to-delivery success, and latency.
- Run a representative performance test and record resource use, message rates, and latency before saturation.
- Observe at least 1 normal business cycle and identify daily or weekly peaks.
- Set warning thresholds below the tested safe capacity, leaving enough time to add capacity or schedule maintenance. Set critical thresholds at the point where immediate action is required.
- Revisit thresholds after traffic growth, topology changes, upgrades, or changes to persistent sessions and data integrations.
Avoid alerting only on a fixed percentage. Trend and forecast alerts, such as disk exhaustion predicted within 24 hours or connections reaching tested capacity within a week, often provide more useful maintenance lead time.
Leading Indicators to Monitor
Preventive alerts should detect a deteriorating condition while the cluster is still serving traffic. Use a warning threshold that leaves time for investigation and maintenance, and a critical threshold for conditions that require immediate action. For each condition, the following guidance lists relevant signals and suggested actions for operators.
Cluster and Runtime Health
Mria replication pressure
- Early-warning condition: Replication lag or queues stay above their normal peak, or continue growing instead of draining.
- Relevant signals: On Replicant nodes, monitor
emqx_mria_lag,emqx_mria_message_queue_len, andemqx_mria_replayq_len. On Core nodes, monitoremqx_mria_server_mqlandemqx_mria_weight. - Suggested actions: Correlate the metric change with logs from both the Replicant and its upstream Core node. Look for lag-collection failures, busy distribution ports, long scheduler pauses, Mnesia overload, and Mria replication errors. Then check network latency and loss, CPU, and disk I/O. Reduce write pressure or add Core capacity before Replicants fall further behind.
emqx_mria_lag is the number of transactions by which a Replicant shard is behind its upstream Core shard; it is not a duration in seconds. Short spikes can be normal during bursts of writes. Alert when the value remains above the maximum observed during representative peak traffic, or when it and the Mria queue metrics show a sustained positive trend. Group alerts by both node and shard, because one shard can be unhealthy while others continue to replicate normally. For details about each Mria metric, see Monitor and Debug.
Configuration convergence
- Early-warning condition:
emqx_conf_sync_txiddiffers between nodes for longer than a normal configuration rollout. - Relevant signals:
emqx_conf_sync_txidfrom every node and configuration synchronization logs. - Suggested actions: Stop further configuration changes, identify the node that is behind, and inspect cluster connectivity and configuration synchronization errors. Restore convergence before maintenance or another configuration change.
Runtime backlog
- Early-warning condition: Run queue or mailbox sizes stay above their established baseline.
- Relevant signals:
emqx_vm_run_queue,emqx_vm_mnesia_tm_mailbox_size,emqx_vm_broker_pool_max_mailbox_size, built-in overload alarms, andbusy_dist_portevents. - Suggested actions: Investigate sustained overload, slow storage, or cluster communication before request latency and queues grow further.
Resource and Capacity
CPU pressure
- Early-warning condition: CPU remains above the normal peak for 10 to 15 minutes.
- Relevant signals:
emqx_vm_cpu_use, host CPU, load, and container throttling. - Suggested actions: Find the workload or integration causing the increase. Rebalance traffic or add capacity before saturation. EMQX's built-in CPU alarm defaults to 80%.
Memory pressure
- Early-warning condition: Memory remains above the warning threshold or is growing toward the host or container limit.
- Relevant signals:
emqx_vm_used_memory,emqx_vm_total_memory, host or container memory, and EMQX memory alarms. - Suggested actions: Inspect connection, session, queue, and integration growth. Starting from EMQX 6.3.0, use
emqx ctl session-topto identify sessions that retain the most MQTT payload bytes or have the longest message queues. Add capacity or reduce the source of growth before the operating system terminates the process. EMQX's built-in system-memory alarm defaults to 70%.
Overload-protection activity
- Early-warning condition: Overload-protection counters increase, especially connection closures or delay timeouts.
- Relevant signals:
emqx_overload_protection_new_conn,emqx_overload_protection_delay_timeout,emqx_overload_protection_delay_ok,emqx_overload_protection_gc, andemqx_overload_protection_hibernation. These metrics are exported only when overload protection is enabled. - Suggested actions: The broker is already mitigating resource pressure. Correlate the events with CPU, memory, run queue, mailboxes, and connection churn. Reduce load or add capacity before more client traffic is affected.
Disk pressure
- Early-warning condition: Free space falls below the operational reserve or is predicted to run out before the next maintenance window.
- Relevant signals: Host or volume free bytes, free inodes, I/O latency, and disk growth rate.
- Suggested actions: Remove data according to the retention policy or expand the volume. A common starting point is a warning at 20% free and a critical alert at 10% free.
Broker capacity
- Early-warning condition: Connections, sessions, subscriptions, or topics approach the tested or licensed operating limit.
- Relevant signals:
emqx_connections_count,emqx_sessions_count,emqx_subscriptions_count,emqx_topics_count, and, in EMQX Enterprise,emqx_license_max_sessions. - Suggested actions: Compare growth with capacity-test results. Add nodes or move traffic before reaching the limit. Do not treat the historical
*_maxgauges as configured capacity limits.
Message Delivery and Dependencies
Message loss
- Early-warning condition: Unexpected drop counters increase.
- Relevant signals:
emqx_messages_dropped_*andemqx_delivery_dropped_*. - Suggested actions: Investigate the specific reason. Queue-full, quota-exceeded, receive-maximum, and expired-message drops can indicate overload or incorrect limits.
no_subscribersandno_localdrops can be expected in some applications.
Authentication and authorization dependency health
- Early-warning condition: An enabled provider or source is not connected (its status is
0), authentication or authorization latency rises above the normal peak, or authentication failures or authorization denials increase unexpectedly. - Relevant signals:
emqx_authn_enable,emqx_authn_status,emqx_authn_latency,emqx_authn_failed,emqx_authz_enable,emqx_authz_status,emqx_authz_latency, andemqx_authz_denyfrom/api/v5/prometheus/auth. - Suggested actions: Check the external database, HTTP service, LDAP server, network, and connection pool. Correlate a failure spike with client traffic to distinguish a backend problem from invalid credentials, an application change, or an attack.
Data integration health
- Early-warning condition: An enabled connector or action is disconnected;
emqx_action_queuingoremqx_action_inflightgrows instead of draining; or late replies, retries, failures, or drops increase. - Relevant signals:
emqx_connector_enable,emqx_connector_status,emqx_action_enable,emqx_action_status,emqx_action_queuing,emqx_action_inflight, and related action metrics from/api/v5/prometheus/data_integration, plus EMQXresourcealarms. - Suggested actions: Check the external service and network, then verify buffer capacity and retry behavior. Growing queues and in-flight requests can provide warning before failures and drops begin.
Expiry Risks
Certificate and license expiry
- Early-warning condition: Expiry is within the organization's renewal lead time.
- Relevant signals:
emqx_cert_expiry_atand, in EMQX Enterprise,emqx_license_expiry_at. - Suggested actions: Renew and deploy the certificate or license. A common starting point is a warning 30 days before expiry and a critical alert 7 days before expiry.
Verify Metric Availability
For the descriptions of broker counters displayed in the Dashboard, see Statistics and Metrics. Basic broker, authentication and authorization, and data integration metrics are exposed through separate Prometheus endpoints. Metric availability can vary by edition and enabled features. Inspect the relevant endpoint in your deployment before creating rules.
Centralize Logs and Alert Selectively
Collect Logs Outside the Cluster
Do not keep the only copy of a node's logs on that node. A node failure can make the evidence needed to diagnose it unavailable. Send logs from every node to a central system outside the EMQX cluster and include labels for the cluster, node, node role, EMQX version, and availability zone.
Use JSON log format and retain at least warning, error, and critical events. Logs can be collected from console or file output, or exported through OpenTelemetry. For configuration and production collection guidance, see Logs.
Monitor the log collector and transport by using their health metrics or an explicit heartbeat that does not depend on application log volume. Do not alert merely because a node produces no logs; an idle or healthy node may have nothing to report at the configured severity.
Define Targeted Log Alerts
Use the following events and guidance to define log-based alert rules:
| Condition | Log Signal | Alerting Guidance |
|---|---|---|
| Mria lag observation failed | prometheus_mria_shard_lag_refresh_exception | Alert if it occurs repeatedly. The exporter caches Mria lag; if a refresh times out, the previous value can continue to be exported and appear stable. |
| Erlang VM or inter-node communication pressure | busy_dist_port, long_schedule, long_gc, and Mnesia overload messages | Alert on a sustained rate or repeated events and correlate them with Mria queues, CPU, and latency. These events can precede client-visible degradation. |
| Mria replication or topology failure | gap_in_the_tlog and mria_lb_split_brain | Notify the responsible operator immediately. Capture the node, shard, agent, expected sequence number, and actual sequence number from the structured fields. |
| Session buffer payload pressure | session_buffer_high_watermark | Investigate every warning. If the threshold represents an actionable per-session risk, configure an alert. Raise the alert priority when warnings occur for multiple clients or correlate with increased memory use or busy_dist_port. Capture clientid, mqueue_length, inflight_count, total_payload_bytes, and total_payload_bytes_high_watermark, and use emqx ctl session-top to identify the sessions retaining the most payload bytes. |
| Buffering or message-queue pressure | data_bridge_buffer_overflow, unrecoverable_resource_error, and dropped_msg_due_to_mqueue_is_full | Alert when these events are unexpected or exceed the application's accepted loss rate. Correlate them with action and message-drop counters. |
| Configuration synchronization failure | sync_data_from_node_failed and cluster_rpc_apply_failed | Alert immediately when a configuration change or node startup is in progress; verify that all nodes have converged on the intended configuration. |
Not every warning-level log requires immediate operator notification. Authentication failures and malformed client traffic, for example, may be expected at low rates. Base alerts on selected msg values, severity levels, sustained event rates, or deviations from the normal baseline. Treat unexpected critical events as immediately actionable.
Account for Log Throttling
EMQX throttles selected repetitive log events. A log query can therefore undercount the original events. Include log_events_throttled_during_last_period in dashboards and alerts, and use its dropped field to determine which messages were suppressed. For details, see Log Throttling.
Detect Failures Separately
The indicators in Leading Indicators to Monitor provide advance warning, but they do not replace failure-detection alerts. The following conditions indicate that service or redundancy has already been lost. Configure alerts to notify the responsible operator immediately when any of these conditions occurs:
- Prometheus
up == 0 - A failed synthetic MQTT check
emqx_cluster_nodes_runningfalling below the planned cluster sizeemqx_cluster_nodes_stoppedincreasing- An unexpected reset of
emqx_vm_uptime_ms - An EMQX
partitionalarm
Use the early-warning indicators described in Leading Indicators to Monitor to detect deterioration early and provide enough time to schedule maintenance before these failures occur.
Example Prometheus Alert Rules
You can copy the following configuration as a starting point for Prometheus alert rules. Before using it in production:
- The example uses the job names from the Prometheus server configuration example. Update the
jobmatchers if your scrape jobs use different names. - The cluster-loss rule assumes a planned cluster size of 3 nodes. Replace
3with the planned size of your cluster. - Replace the other example thresholds with values appropriate for your deployment.
- If a Prometheus job contains multiple clusters, aggregate the configuration-convergence rule by a cluster label.
- Add an absolute threshold based on your peak-traffic baseline to the Mria trend rules. The example rules detect a queue or lag with a sustained positive slope, but a large, stable backlog should also trigger an alert.
- Add host- or platform-specific rules for disk exhaustion, memory limits, container restarts, and network health.
groups:
- name: emqx-early-warning
rules:
- alert: EMQXMRIAReplicationLagGrowing
expr: deriv(emqx_mria_lag{job="emqx_stats"}[10m]) > 0
for: 10m
labels:
severity: warning
annotations:
summary: "Mria replication lag is growing on {{ $labels.instance }} shard {{ $labels.shard }}"
- alert: EMQXMRIAReplicationQueueGrowing
expr: deriv(emqx_mria_server_mql{job="emqx_stats"}[10m]) > 0 or deriv(emqx_mria_message_queue_len{job="emqx_stats"}[10m]) > 0 or deriv(emqx_mria_replayq_len{job="emqx_stats"}[10m]) > 0
for: 10m
labels:
severity: warning
annotations:
summary: "A Mria replication queue is growing on {{ $labels.instance }} shard {{ $labels.shard }}"
- alert: EMQXSustainedHighCPU
expr: emqx_vm_cpu_use{job="emqx_stats"} > 80
for: 10m
labels:
severity: warning
annotations:
summary: "EMQX CPU usage is high on {{ $labels.instance }}"
- alert: EMQXSustainedHighMemory
expr: 100 * emqx_vm_used_memory{job="emqx_stats"} / emqx_vm_total_memory{job="emqx_stats"} > 70
for: 10m
labels:
severity: warning
annotations:
summary: "EMQX host memory usage is high on {{ $labels.instance }}"
- alert: EMQXOverloadProtectionActive
expr: sum by (instance) (increase(emqx_overload_protection_new_conn{job="emqx_stats"}[5m])) > 0 or sum by (instance) (increase(emqx_overload_protection_delay_timeout{job="emqx_stats"}[5m])) > 0
labels:
severity: warning
annotations:
summary: "EMQX overload protection is closing or timing out client work on {{ $labels.instance }}"
- alert: EMQXConfigurationNotConverged
expr: max(emqx_conf_sync_txid{job="emqx_stats"}) != min(emqx_conf_sync_txid{job="emqx_stats"})
for: 5m
labels:
severity: warning
annotations:
summary: "EMQX nodes report different configuration transaction IDs"
- alert: EMQXDeliveryQueueFullDrops
expr: sum by (instance) (increase(emqx_delivery_dropped_queue_full{job="emqx_stats"}[5m])) > 0
labels:
severity: warning
annotations:
summary: "EMQX dropped messages because a delivery queue was full"
- alert: EMQXActionQueueGrowing
expr: deriv(emqx_action_queuing{job="emqx_data_integration"}[10m]) > 0
for: 10m
labels:
severity: warning
annotations:
summary: "EMQX data integration action {{ $labels.id }} has a growing queue on {{ $labels.instance }}"
- alert: EMQXActionFailures
expr: sum by (instance, id) (increase(emqx_action_failed{job="emqx_data_integration"}[5m])) > 0
labels:
severity: warning
annotations:
summary: "EMQX data integration action {{ $labels.id }} is failing"
- alert: EMQXAuthenticationBackendUnavailable
expr: (emqx_authn_enable{job="emqx_auth"} == 1 and on (instance, id) emqx_authn_status{job="emqx_auth"} == 0) or (emqx_authz_enable{job="emqx_auth"} == 1 and on (instance, type) emqx_authz_status{job="emqx_auth"} == 0)
for: 2m
labels:
severity: warning
annotations:
summary: "An enabled EMQX authentication or authorization backend is unavailable on {{ $labels.instance }}"
- alert: EMQXCertificateExpiresSoon
expr: emqx_cert_expiry_at{job="emqx_stats"} > 0 and (emqx_cert_expiry_at{job="emqx_stats"} - time()) < 30 * 24 * 60 * 60
for: 1h
labels:
severity: warning
annotations:
summary: "EMQX listener certificate expires within 30 days"
- name: emqx-failure-detection
rules:
- alert: EMQXMetricsTargetDown
expr: up{job="emqx_stats"} == 0
for: 30s
labels:
severity: critical
annotations:
summary: "EMQX metrics target {{ $labels.instance }} is unreachable"
- alert: EMQXClusterLostNode
expr: min by (job) (emqx_cluster_nodes_running{job="emqx_stats"}) < 3
for: 2m
labels:
severity: critical
annotations:
summary: "EMQX cluster has fewer than 3 running nodes"Counter metrics normally only increase. Alert on their rate or increase over a time window, not on their absolute value. Use a for duration with resource gauges so that a short traffic spike does not cause an unnecessary alert.
Make Alerts Actionable
Define alert context and ownership.
Each actionable alert should identify the affected cluster and, when applicable, the affected node, current value, and threshold. It should also include a dashboard link, an owner, and a runbook that documents how to investigate, mitigate, and resolve the alert. The runbook should state how to confirm the condition, protect service, restore redundancy, and decide whether to scale, rebalance, restart, or repair.
Test alert delivery and recovery.
Test the full alert path before relying on it. In a non-production environment or during an approved test window, deliberately stop a scrape target, lower a test threshold, and disconnect a test integration. Confirm that the alert reaches the correct operator, contains enough context, and clears after recovery.
Prepare maintenance procedures.
Use warning alerts to schedule maintenance while redundancy remains available. Before changing the cluster, verify that backups are usable, the remaining nodes can carry the load, and the alerting system is healthy. Relevant procedures include Backup and Restore, Node Evacuation and Cluster Load Rebalancing, and EMQX Enterprise Rolling Upgrade.
Production Readiness Checklist
- Every EMQX node and its host or container is visible in the external monitoring system.
- Built-in alarms are forwarded outside EMQX and tested.
- Warning, error, and critical logs from every node are stored centrally, and the collection pipeline is monitored.
- An external synthetic MQTT check covers the production client path.
- Alerts for Mria replication, configuration convergence, and runtime backlog have defined owners and runbooks.
- Alerts for overload protection, CPU, memory, disk, and broker capacity have defined owners and runbooks.
- Alerts for authentication and authorization, message drops, and data integrations have defined owners and runbooks.
- Certificate and license expiry alerts have defined owners and runbooks.
- Selected Mria, VM-pressure, buffer-overflow, and configuration-sync log events have rate-based or immediate alerts appropriate to their severity.
- Separate target-down, synthetic MQTT, cluster-size, and partition alerts detect failures and notify the responsible operator immediately.
- Warning thresholds leave enough time for the team's normal maintenance and capacity-provisioning process.
- Dashboards show both the current value and the trend over a relevant business cycle.
- Alert notifications, backup restoration, and rolling-maintenance procedures are tested regularly.