3 min read

Modernizing Home Telemetry: Why I Switched from Direct Writes to MQTT

Modernizing Home Telemetry: Why I Switched from Direct Writes to MQTT

I'm finally taking a step forward with my home automation setup, and I'm genuinely excited about it. For a while, I'd been running a handful of ESP32s around the house, each directly pushing temperature and humidity data into InfluxDB. It worked... kind of. But it was never quite stable. Any time InfluxDB was down, the data was lost. If network latency got in the way, my ESPs would hang or drop readings. It was a fragile system that felt more like a proof-of-concept than something I could rely on long-term.

This week, I rethought the architecture. Instead of writing directly to InfluxDB, I'm using MQTT to decouple my ESP32s from the rest of the telemetry stack. This simple change opened the door to a more durable and flexible pipeline.

The New Stack

Here's the updated flow:

ESP32 (sensors) --> MQTT (Mosquitto) --> Telegraf --> InfluxDB

Each ESP32 publishes sensor readings as JSON to an MQTT topic. Telegraf subscribes to those topics and forwards the data to InfluxDB, where I can visualize and analyze it in Grafana.

Services Overview

A brief look at the services I deployed in my home lab to support this pipeline:

Mosquitto (MQTT Broker)

Simple message broker where ESP32s publish sensor data:

services:
  mosquitto:
    image: eclipse-mosquitto:2
    container_name: mosquitto
    ports:
      - "1883:1883"    # MQTT
      - "9002:9001"    # WebSocket (optional)
    volumes:
      - ./mosquitto.conf:/mosquitto/config/mosquitto.conf
      - ./data:/mosquitto/data
      - ./log:/mosquitto/log
    restart: always
    logging:
      driver: "gelf"
      options:
        tag: "docker.mosquitto"
        gelf-address: "udp://${LOGSTASH_HOST}:12201"

Telegraf

Subscribes to MQTT and writes to InfluxDB:

services:
  telegraf:
    image: telegraf:1.34.4
    container_name: telegraf
    restart: always
    environment:
      - HOST_PROC=/host/proc
      - HOST_SYS=/host/sys
      - HOST_ETC=/host/etc
    volumes:
      - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
    logging:
      driver: "gelf"
      options:
        tag: "docker.telegraf"
        gelf-address: "udp://${LOGSTASH_HOST}:12201"

InfluxDB

Time-series database storing all ESP32 metrics:
https://github.com/18visions-ci/homelab-influxdb

---
- name: Install and configure InfluxDB 3.0.3
  hosts: influxdb
  become: yes
  become_method: sudo
  become_user: root
  vars:
    influxdb_admin_user: "admin"
    influxdb_admin_password: "{{ lookup('env', 'influxdb_admin_pw') }}"
    influxdb_org: "homelab"
    influxdb_bucket: "esp32_data"
    influxdb_token: "{{ lookup('env', 'influxdb_tkn') }}"
    influxdb_retention: "17520h"
    influxdb_version: "3.0.3"

  roles:
    - influxdb_install
    - influxdb_configure

Each of these services runs in my Proxmox-based homelab using lightweight VMs or containers, managed via Ansible and GitHub Actions.

Why I Switched

When I was posting directly to InfluxDB:

  • If InfluxDB was down, the ESP32s lost data
  • The HTTP client on the ESPs was fragile
  • Writing from embedded code meant I needed to hardcode authentication, bucket, org, and token logic

With MQTT + Telegraf:

  • ESP32s are now fire-and-forget. They just publish JSON to a broker.
  • Telegraf handles batching, retries, and formatting for InfluxDB.
  • If Influx or Telegraf go down, Mosquitto still holds messages in memory (or disk, if configured).

Pros and Cons

Direct to InfluxDB (old setup):

  • ✅ Simple architecture (1 device talks to 1 endpoint)
  • ❌ Prone to failure when the network or InfluxDB is unavailable
  • ❌ Requires HTTPS, token handling, and manual JSON formatting
  • ❌ ESP32s do all the heavy lifting

MQTT + Telegraf (new setup):

  • ✅ Decouples producer from consumer
  • ✅ More resilient (in case of failure)
  • ✅ Easier to expand (add a second database, push to cloud, etc.)
  • ✅ Lightweight JSON from ESPs
  • ❌ Adds more services to maintain (Telegraf, Mosquitto)
  • ❌ Slightly steeper initial setup

A Bonus: OTA Updates

Another big win this time around was setting up OTA (Over-The-Air) firmware updates for my ESP32s. Once I had stable Wi-Fi and MQTT connections, I added ArduinoOTA support to each sketch and was able to push firmware updates from my laptop without ever plugging in a USB cable. It took some trial and error with partition schemes and port binding, but now it's working flawlessly.

Wrapping It Up

The new setup already feels so much more stable. My ESP32s don’t care if InfluxDB is momentarily unavailable. OTA lets me make improvements quickly, and MQTT + Telegraf smooth out the edges between my devices and my database.

I'll add code snippets and configurations in follow-up posts, but for now, I'm thrilled to have a telemetry pipeline that actually feels production-ready — even if it’s just for a home lab.

Stay tuned for more home automation posts coming soon!