Tutorials

Visualize MQTT Data in Grafana with the MQTT Data Source

Stream MQTT topics straight into Grafana: install the MQTT data source plugin, connect to your broker with TLS, parse JSON payloads and build live panels.

Updated · 8 min read

Visualize MQTT Data in Grafana with the MQTT Data Source

Grafana can subscribe to an MQTT broker directly. With the official MQTT data source plugin (grafana-mqtt-datasource), every panel query is a topic subscription, and new messages appear on the dashboard within moments of being published — no database in between. It is the fastest way to put a live gauge or chart in front of sensor data.

This tutorial installs the plugin, connects it to a broker over TLS, publishes test telemetry and builds live panels. It also covers the part people usually discover too late: the data source streams, it does not store.

How the MQTT data source works

The plugin runs inside the Grafana server. When a dashboard panel asks for data, the backend opens an MQTT connection (one per data source), subscribes to the topic in the query and forwards every message to the browser through Grafana Live, Grafana's WebSocket streaming channel.

AspectBehavior
Transport to brokerMQTT over TCP or TLS from the Grafana server (not from the browser)
Transport to browserGrafana Live (WebSocket), push-based — no dashboard refresh needed
Payload parsingJSON objects become fields; a plain number becomes a single value field
HistoryNone — only messages received while the panel is open
Best forLive operations views, commissioning, demos, debugging

Because the Grafana server is the MQTT client, the broker must be reachable from wherever Grafana runs, and the credentials live in the data source settings, not in the browser.

Run Grafana with the plugin

The quickest setup is Docker. The plugin is installed at startup from the Grafana plugin catalog:

Start Grafana with the MQTT plugin
docker run -d --name grafana -p 3000:3000 \
  -e GF_INSTALL_PLUGINS=grafana-mqtt-datasource \
  grafana/grafana:latest

On recent Grafana releases, GF_PLUGINS_PREINSTALL=grafana-mqtt-datasource is the newer way to request the same thing. On an existing installation, use the CLI and restart the service:

Install on a package-based Grafana
grafana cli plugins install grafana-mqtt-datasource
sudo systemctl restart grafana-server

Open http://localhost:3000, log in (default admin / admin, then change it), and go to Connections → Data sources → Add data source → MQTT.

Connect the data source to your broker

The settings page asks for a URI, optional credentials and TLS options:

  • URI — tcp://broker.connectmq.com:1883 for a quick plaintext test, tls://broker.connectmq.com:8883 for TLS (some plugin versions also accept ssl://). Use TLS for anything beyond a demo.
  • Username / Password — the credentials of your broker. With per-topic ACLs, grant this user read access only to the topics dashboards need.
  • TLS — enable "With CA Cert" if your broker uses a private CA, or client-certificate auth for mTLS.

Click Save & test. A successful test means the Grafana server could open an MQTT connection. If it fails, the error is the broker's CONNACK or a network error — see MQTT connection errors and look up return codes with the reason code tool.

For repeatable setups, provision the data source from a file instead of clicking:

provisioning/datasources/mqtt.yaml
apiVersion: 1
datasources:
  - name: MQTT
    type: grafana-mqtt-datasource
    access: proxy
    jsonData:
      uri: tls://broker.connectmq.com:8883
      username: ${MQTT_USER}
    secureJsonData:
      password: ${MQTT_PASS}

Grafana expands environment variables in provisioning files, so the password never lands in Git. Field names can differ slightly between plugin versions; if a value is ignored, configure it once in the UI and compare with the plugin's README.

Publish test telemetry

A panel only shows messages that arrive while it is open, so you need a steady stream to design against. This paho-mqtt 2.x script publishes a JSON reading every second:

fake_sensor.py
import json, math, os, random, time
import paho.mqtt.client as mqtt

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="grafana-demo-sensor")
client.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"])
client.tls_set()                       # system CA store
client.connect("broker.connectmq.com", 8883)
client.loop_start()

t = 0
while True:
    reading = {
        "temperature": round(21 + 3 * math.sin(t / 30) + random.uniform(-0.3, 0.3), 2),
        "humidity": round(45 + random.uniform(-2, 2), 1),
        "battery": max(0, 100 - t // 60),
    }
    client.publish("testmqtt/grafana/room1/telemetry", json.dumps(reading), qos=0)
    t += 1
    time.sleep(1)

Before touching Grafana, confirm the stream with the online MQTT client: subscribe to testmqtt/grafana/# and watch the messages arrive. If they show up there but not in Grafana, the problem is in the data source, not the publisher.

Watch the test telemetry in your browser

Build live panels

Create a dashboard, add a visualization and select the MQTT data source. The query editor has one important field, Topic: enter testmqtt/grafana/room1/telemetry.

  1. Time series — the default. Each JSON key (temperature, humidity, battery) becomes a series. Set the dashboard time range to Last 5 minutes so the chart scrolls instead of compressing.
  2. Gauge — switch the visualization, set Calculation to Last and pick the temperature field under Fields. Add thresholds (green below 25, red above 28).
  3. Stat — good for battery; use Last and a unit of percent.

If you only want one field in a panel, use the Organize fields or Filter fields by name transformation rather than publishing separate topics.

Payload formats that work

PayloadResult in Grafana
23.5One numeric field (value)
{"temperature": 23.5, "humidity": 41}Two numeric fields
{"env": {"temp": 23.5}}Nested keys are flattened into field names
{"status": "ok"}A string field — fine for a table, not for a chart
Binary, CBOR, ProtobufNot parsed — decode upstream first

The timestamp is the time Grafana received the message, not a time field inside your payload. If devices buffer and send late, the chart will show arrival time; see timestamp issues.

Wildcards and many devices

Recent plugin versions accept + and # in the topic field, so testmqtt/grafana/+/telemetry can feed one panel from every room. Check which topics a filter will match with the topic matcher before saving it — a stray # on a busy broker streams far more data into the browser than a panel can draw. For large fleets, prefer one panel per device group, or aggregate on the device side and publish a summary topic. See topics and wildcards for designing topics that dashboards can filter cleanly.

Troubleshooting

  • "No data" on a new panel — nothing has been published since the panel opened. The plugin does not replay old messages, and retained messages are only useful if the publisher sets the retain flag. Start the test publisher and wait a second.
  • Save & test fails — check that the Grafana server (or container) can reach the broker: docker exec grafana nc -vz broker.connectmq.com 8883. Corporate egress rules often block 8883 even when your laptop can connect.
  • Data appears, then stops — another client with the same client ID is kicking Grafana off, or the user lacks read permission and the broker silently drops the subscription. Look at broker logs and verify ACLs.
  • Numbers show as strings — the publisher sends "23.5" in quotes. Fix the payload or add a Convert field type transformation.
  • Panel lags or the tab freezes — the topic filter is too broad or devices publish faster than you need. Lower the publish rate or aggregate first.

When you need history

The MQTT data source is perfect for "what is happening right now". As soon as someone asks "what happened last night", you need storage. The common pattern is to keep the live panel and add a second data source:

Grafana can show both on the same dashboard: a live MQTT stat at the top, historical InfluxDB or SQL charts below. If you are looking for a browser-only dashboard without Grafana, see building a live MQTT dashboard.

The MQTT data source turns a topic into a live panel in minutes. Point it at a broker user with read-only access, keep payloads as flat JSON numbers, verify the stream with an MQTT client first, and add a database when the dashboard needs to remember.

Frequently asked questions

Does the Grafana MQTT data source store history?

No. It subscribes to topics and streams new messages into panels through Grafana Live. Data lives only in the browser's buffer, so a page reload starts empty. For history, write MQTT data to a database such as InfluxDB or TimescaleDB and query that instead.

Can I use wildcards in the Grafana MQTT topic field?

Recent versions of the plugin accept the + and # wildcards. Older releases only subscribe to exact topics. If a wildcard query shows no data, update the plugin or query a concrete topic first to confirm that the connection works.

Why does my Grafana MQTT panel show 'No data'?

Usually the topic does not match what devices publish, nothing is being published right now (the plugin only shows new messages), or the payload is not JSON or a plain number. Publish a test message from an MQTT client while the panel is open to narrow it down.