The “Just Use ESPHome” Assumption Doesn’t Always Hold
You’ve probably heard it a thousand times in the home automation discord: “Just use ESPHome, it’s the modern way.” And honestly? For 80% of greenfield setups, they’re right. ESPHome is fantastic, declarative YAML, Home Assistant integration that just works, no fiddling with MQTT brokers if you don’t want to.
But then you inherit a closet full of Sonoff Basic devices from 2019. Or your partner buys a $12 Shelly 1 relay because it was on Amazon and they thought it was “smart.” Or you’ve got a zigbee2mqtt gateway running on a Pi and you want the smartest possible device talking to it and nothing else.
That’s when ESPHome’s opinions start feeling like constraints. That’s when you end up reading Tasmota docs at 2 AM wondering why you didn’t just flash the thing from the start.
Tasmota isn’t the “modern” choice. It’s the pragmatic choice for certain jobs. Let me show you when.
The Fundamental Difference: Philosophy
ESPHome is Home Assistant-first and proud of it. You write YAML, it generates C++, compiles it, flashes it. The device boots and immediately speaks the ESPHome protocol back to HA. Pretty? Yes. Elegant? Absolutely. But the assumption is that Home Assistant is your hub, and you’re building for it.
Tasmota is MQTT-first and firmware-agnostic. You flash the binary, boot the device, configure it via its web UI or MQTT commands, and it becomes an MQTT client. It doesn’t care about Home Assistant. It could be talking to OpenHAB, Node-RED, a custom Python script, or a shell script that publishes to a broker. The device is a node in your MQTT network, not an extension of Home Assistant.
This isn’t a philosophical preference. It’s a load-bearing difference when you’re retrofitting.
When You Pick Tasmota: The Scenarios
1. Legacy Hardware That ESPHome Doesn’t Support Well
ESPHome has excellent hardware support if you’re buying new ESP32-S3 boards. But legacy stuff? It’s a crapshoot.
Take the Sonoff Basic (the original, from 2016). It’s an ESP8266 with a relay, a button, and an LED. Dirt cheap. Millions sold. ESPHome technically supports it, but you’re working with 4 MB of flash on a device that was never meant to run modern toolchains. The binary bloats. OTA updates get dicey. WiFi stability is mediocre because the factory firmware already stretched the hardware.
Tasmota’s binaries for the same device? Optimized within an inch of their lives. Lighter. Faster. Proven on millions of real deployments. Because Tasmota has spent 7+ years tuning for the exact hardware that ESPHome is still figuring out.
Shelly devices are another case. Sonoff’s competitor, Shelly makes relay boards, wall switches, and dimmers that are well-engineered. They come with Shelly’s own cloud-dependent firmware. Tasmota has first-class support for like 40 Shelly models. ESPHome’s Shelly support exists but isn’t as battle-tested.
2. You Already Run MQTT and Want the Device to Be MQTT-Dumb
Here’s a scenario: you’ve got Home Assistant, but you also have Node-RED automation, a Grafana dashboard pulling metrics, and a custom Python script that does silly things at 2 AM based on sensor thresholds.
With ESPHome, every device talks to Home Assistant. Home Assistant is the hub. If HA goes down (updates, crashes, you’re tweaking the config), those devices go dark.
With Tasmota, every device is a direct MQTT client. Publish to cmnd/livingroom_light/POWER and it switches. It doesn’t care if HA is running. Your Node-RED flow can read the same MQTT topics. Your Grafana dashboard can scrape Tasmota’s JSON endpoints. You’ve got redundancy and decoupling for free.
Want to query a Tasmota device’s status without HA? mosquitto_pub -h broker -t 'cmnd/mydevice/STATUS' -m '0' and read the response on stat/mydevice/STATUS. Try that with ESPHome without writing a whole service.
3. You Need the Features Tasmota Has and ESPHome Doesn’t (Yet)
Tasmota has some wild stuff that ESPHome is still catching up on:
- Rules engine: Automation logic on the device itself. Sunrise/sunset timers, multi-step sequences, threshold logic, all without touching HA.
Rule1 on ADC#Voltage>3200 do Publish stat/alert OVERVOLT endonRule2 on Switch1#State=1 do SetOption1 1 | Delay 2000 | SetOption1 0 endonThis lives on the device. Fires every time. No network latency, no HA dependency.
-
Timers: Native scheduling via a JSON payload.
Timer1 {"Enable":1,"Time":"07:00","Days":"1111111","Repeat":1,"Output":1,"Action":1}turns on every day at 7 AM, period. No Home Assistant scenes, no automations, no YAML. It’s on the device. -
Berry scripts: Tasmota has a Lua-like scripting engine. Not for the faint of heart, but it lets you do complex logic on the device itself.
-
Template system: Got a weird device that isn’t in Tasmota’s database? Define the GPIO mapping, pin types, and MQTT topics via template. ESPHome requires code changes and recompilation.
4. You’re Building a Closed-Loop System
Imagine a greenhouse with a temperature sensor, a humidity sensor, and a fan relay. You want: if humidity > 70% and temp > 25°C, turn on the fan for 5 minutes, then wait 10 minutes before checking again.
With ESPHome, that logic lives in HA (or you code it into the firmware). The device reports, HA decides, the device acts.
With Tasmota rules, that entire loop runs on the device.
Rule1 on SI7021#Humidity>70 do Power1 1 endonRule2 on Timer1#Finished do Power1 0 | Backlog 0 | Delay 600000 | RuleTimer1 300000 endonRule3 on SI7021#Temperature>25 do RuleTimer1 1 endonYeah, the syntax is terse. But it’s also: no network required, no latency, no single point of failure for that logic.
The Trade-Off: Why ESPHome Still Wins for New Projects
Tasmota is powerful. It’s also opaque. You’re dealing with a pre-compiled binary doing its own thing. Debugging is harder. The web UI is functional but dated. Configuration is MQTT commands and browser consoles, not declarative YAML.
ESPHome is:
- Transparent: You see the YAML that generates the C++. You can modify it, recompile, flash OTA in seconds.
- Version-controlled: Your YAML lives in git. Reproducible. Auditable.
- Integrated: Home Assistant knows about every entity. Automations are first-class citizens in HA.
- Modern: Active development, newer language features, better error messages.
For new deployments where you control the hardware, ESPHome is the right default. It’s not even close.
But if you’re stuck with a device that ESPHome doesn’t handle well, or you need MQTT-native behavior, Tasmota will get the job done faster than fighting with ESPHome for hours.
Flashing Tasmota: The Practical Part
You don’t need to be afraid of flashing. Here’s the script:
Get Your Device Into Flash Mode
Most Sonoff/Shelly devices have a button labeled “IO0” (or just “0”). While holding it, power on the device. The LED will blink differently. You’re in bootloader mode.
If your device is already running old firmware and the button trick doesn’t work, you might need to erase the flash:
esptool --port /dev/ttyUSB0 erase-flashThen try the button+power again.
Download the Right Binary
Go to https://tasmota.github.io/install/. Select your device type (Sonoff Basic, Shelly 1, etc.), and it’ll give you the recommended binary download.
For Sonoff Basic: tasmota.bin or tasmota-lite.bin (if flash space is tight).
For Shelly 1: tasmota-shelly.bin.
Flash It
Using esptool (Python):
pip install esptoolesptool --port /dev/ttyUSB0 --baud 460800 write-flash -fm dout 0x0 tasmota.bin(esptool v5 dropped the .py suffix and switched commands to dashes, write-flash, erase-flash. The old esptool.py write_flash form still works but nags you with a deprecation warning.)
The dout mode matters for some devices. Sonoff Basic needs dout. Shelly 1 might need dio. Check your device docs, if you’re wrong, the device just won’t boot, no harm done. Reflash with the right mode.
If you’re on Windows, use Tasmota’s built-in web flasher: https://tasmota.github.io/install/. Plug in USB, click “Connect”, select your device, it handles the details.
First Boot and WiFi Setup
The device boots and broadcasts an AP named tasmota-XXXX. Connect to it (password: none), open a browser to 192.168.4.1, and configure your WiFi SSID and password.
Once it connects to your home WiFi, find its IP on your router (or check the serial console). Open http://tasmota-device-ip/ and you’re in the web UI.
Basic MQTT Configuration
If you’re running a Mosquitto broker (likely on the same Pi running Home Assistant or a dedicated box), configure Tasmota to talk to it:
- Configuration → MQTT tab
- Set Host to your broker IP or hostname
- Set User and Password if your broker requires auth (it should)
- Set Topic to something like
home/livingroom/light1(it becomes the device’s MQTT prefix) - Click Save
The device will restart and start publishing/subscribing to topics like:
tele/home/livingroom/light1/STATE: current state (JSON)cmnd/home/livingroom/light1/POWER: send commands here
You can now control it from the command line:
mosquitto_pub -h broker-ip -u user -P pass \ -t "cmnd/home/livingroom/light1/POWER" -m "ON"Or from Node-RED, Home Assistant (via MQTT integration, not native), or anything else that speaks MQTT.
Rules: Doing Smart Things On the Device
Let’s say you want the device to turn on at sunrise and turn off at sunset (assuming you’re in a known location).
Rule1 ON Time#Minute=0 DO Backlog Power 1 ENDONThis fires every hour at minute 0. Not ideal for sunrise/sunset, but you get the idea.
Better: use the built-in timers, which take a JSON payload. Set your latitude/longitude first, then Mode 1 (sunrise) or 2 (sunset) does real sunrise/sunset scheduling, Time becomes an offset.
Timer1 {"Enable":1,"Mode":1,"Time":"00:00","Window":0,"Days":"1111111","Repeat":1,"Output":1,"Action":1}Timer2 {"Enable":1,"Mode":2,"Time":"00:00","Window":0,"Days":"1111111","Repeat":1,"Output":1,"Action":0}Or if you want to get fancy and do multi-step logic (e.g., “if PIR sensor triggers AND it’s after sunset, turn on light for 5 minutes”):
Rule1 ON SWITCH1#State=1 DO Backlog Power1 1 | RuleTimer1 300 ENDONRule2 ON Timer1#Finished DO Power1 0 ENDONRule3 ON TIME#Minute=0 DO Publish cmnd/status/all "" ENDONThe syntax is terse. Read the Tasmota docs (they’re actually pretty good). But once you wrap your head around it, you’ve got a scriptable device that doesn’t need HA to function.
The Console: Your Debugging Superpower
Open Console in the Tasmota web UI and you can type MQTT commands directly. This is gold for testing:
Power 1 ← turns on relayPower 0 ← turns offStatus 0 ← shows device infoStatus 8 ← shows sensor dataBacklog Power 1 | Delay 5000 | Power 0 | Delay 5000 | Power 1 ← sequence commandsMQTT_RETRY 5 ← set MQTT retry countSetOption0 0 ← toggle options (there are dozens)When something’s not working, the console is your friend. You see exactly what the device is doing.
When to Pick Tasmota: Decision Tree
- Are you buying new hardware? → ESPHome
- Is it a Sonoff/Shelly device from 2018 or earlier? → Tasmota
- Do you need device-side automation logic? → Tasmota (ESPHome can’t do per-device rules)
- Do you have multiple hubs and want MQTT as the common protocol? → Tasmota
- Does your device have weird GPIO you can’t describe in YAML? → Tasmota template system
- Do you want everything in git and reproducible? → ESPHome
- Is this greenfield? → ESPHome
Tasmota isn’t the future of home automation. ESPHome is. But Tasmota is the pragmatist’s toolkit for retrofitting the past.
And sometimes, when you’ve got a bin full of old Sonoff relays and they actually work, there’s something to be said for the device that just does its job without needing you to recompile firmware three times before it boots.