The Light Turned On at 3am Again. The Automation Worked Perfectly.
There’s a well-documented phenomenon in home automation circles: your automations work exactly as written, and exactly as written is not what you meant. You wanted the hallway light to turn on when motion is detected after dark. What you got is the hallway light turning on at 3am when the cat walked through, waking up everyone within earshot, because you forgot that “after dark” and “when people are sleeping” are different conditions.
This is not a Home Assistant problem. This is a logic problem. And Node-RED exists to make complex logic possible without writing YAML until your soul leaves your body.
Why Home Assistant
Home Assistant is the self-hosted smart home platform. The pitch: 3,000+ integrations, all running locally, zero cloud dependency, your data stays in your house.
The difference from commercial smart home platforms: when Google shuts down Nest’s local API (which happened), Home Assistant users found workarounds. When SmartThings changed its architecture (which happened), Home Assistant kept working. Local control means your home automation doesn’t break because a company pivoted.
Beyond the philosophical argument: latency. Local automations execute in milliseconds. Cloud-dependent automations execute in seconds, when the cloud is up. A light switch that takes two seconds to respond is a bad light switch.
Docker Compose vs HAOS: Which Installation to Use
This is the most common decision point for new users.
Home Assistant OS (HAOS): A full operating system purpose-built for HA. Recommended for dedicated hardware (old PC, NUC, Raspberry Pi). Best integration with add-ons (the HA add-on store). Simplest update path. If you’re dedicating hardware to this, use HAOS.
Home Assistant Container (Docker): Just the core HA application in a container. No add-on store (add-ons are separate containers you manage yourself). More flexible for machines running other things. If HA is one of many services on your server, use this.
Docker Compose (Container mode):
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
restart: unless-stopped
network_mode: host
privileged: true
environment:
- TZ=America/New_York
volumes:
- ha-config:/config
node-red:
image: nodered/node-red:latest
restart: unless-stopped
ports:
- "1880:1880"
environment:
- TZ=America/New_York
volumes:
- node-red-data:/data
depends_on:
- homeassistant
volumes:
ha-config:
node-red-data:
The network_mode: host for Home Assistant is important — HA needs to discover devices on your local network (mDNS, Zeroconf, UPnP). Bridge networking breaks device discovery.
HA’s Built-In Automations: Where to Start
Home Assistant has a YAML-based automation system that handles most common scenarios well. Understanding it first helps you know when to reach for Node-RED instead.
A basic automation in HA’s YAML:
# configuration.yaml or automations.yaml
automation:
- alias: "Evening lights"
trigger:
- platform: sun
event: sunset
offset: "-00:30:00"
condition:
- condition: state
entity_id: input_boolean.guest_mode
state: "off"
action:
- service: light.turn_on
target:
area_id: living_room
data:
brightness_pct: 60
color_temp: 3000
HA automations are readable and cover trigger → condition → action patterns well. The UI editor (Settings → Automations) handles most of this visually.
Where HA automations struggle:
- Complex multi-step sequences with delays and conditions between steps
- Loops (retry until a condition is met)
- External API calls and response handling
- Debugging (“which step did it fail at?”)
- Shared logic across multiple automations
Connecting Node-RED to Home Assistant
Option 1: HAOS Add-on (Easiest)
If you’re on HAOS, install Node-RED from the add-on store. It automatically connects to HA. No configuration needed.
Option 2: Docker + node-red-contrib-home-assistant-websocket
For Docker installs, you need the Node-RED HA integration:
- In Node-RED, go to Manage Palette → Install
- Install
node-red-contrib-home-assistant-websocket
Then configure the HA server connection:
- Any HA node → edit → Add new server
- Base URL:
http://homeassistant:8123(or your HA URL) - Access Token: HA → Profile → Long-Lived Access Tokens → Create token
Once connected, Node-RED nodes can read HA states, call services, fire events, and subscribe to state changes.
Building Flows: Practical Examples
Presence Detection → Multi-Step Action
The classic problem with basic presence detection: your lights come on the moment you pull into the street, before you’re inside. Or they come on and you walk in, check the mail, and walk to the bedroom — the living room lights were on for 30 seconds.
Node-RED flow for smarter arrival:
[HA state: person.you arrives home]
→ [Delay: 3 minutes] ← wait, maybe it's a quick car retrieval
→ [HA state: check still home?]
→ [Switch: yes/no]
yes → [HA service: turn on welcome scene]
[HA service: disarm alarm]
[Wait 20 minutes]
[HA state: still home & lights on?]
yes → [HA service: dimming sequence]
no → [End]
Implementing this in HA’s YAML automations is possible but verbose. In Node-RED, the flow is visual and each node’s output is debuggable.
Webhook Trigger → Notification → Light Flash
Practical use case: someone rings your doorbell (or your CI pipeline finishes, or your backup completes), you want a notification AND a light flash.
[HTTP In: POST /doorbell]
→ [Change: set payload.person from query]
→ [HA service: notify.mobile_app_your_phone]
data: "{{payload.person}} at door"
→ [HA service: light.flash]
entity_id: light.living_room
flash: short
→ [HTTP Response: 200 OK]
The HTTP In node in Node-RED creates a webhook endpoint at http://nodered:1880/doorbell. Any service that can make an HTTP request can trigger this flow.
Dashboard Button → Complex Sequence
“Goodnight” scene that does multiple things in sequence:
[HA event: input_button.goodnight pressed]
→ [HA service: alarm.arm_home]
→ [Delay: 30s] ← let household finish up
→ [HA service: light.turn_off all except bedroom]
→ [HA service: climate.set_temperature bedroom: 68°F]
→ [HA service: media_player.pause all]
→ [Delay: 1 hour]
→ [HA state: still asleep? (no motion for 30min)]
→ [HA service: light.turn_off bedroom]
The timing and conditional logic here would be multiple separate HA automations with input_boolean flags to coordinate them. In Node-RED it’s one flow.
Debugging: Node-RED’s Killer Advantage
Every node in a Node-RED flow has a debug tab. During development:
- Add a
debugnode after any node you want to inspect - Run the flow
- Watch the debug sidebar populate with real message data
You can see exactly what data is flowing through your automation at every step. When an HA automation mysteriously doesn’t fire, you’re left checking logs and adding trace conditions. In Node-RED, you click the node and watch the data in real time.
The inject node (for manual triggering) is also invaluable: click it to fire the flow manually without waiting for the real trigger condition.
Practical Flows Worth Building
Energy monitoring alerts: Node-RED reads your smart plug power consumption, calculates rolling averages, alerts when a device is drawing unexpected power (washing machine done, dryer stuck running overnight).
Complex presence detection: Use multiple inputs — phone GPS, WiFi SSID, router DHCP table — to determine if someone is actually home. Compare with just device_tracker entity for dramatically fewer false positives.
External API integration: Call a weather API, parse the response, use it to decide whether to run irrigation. HA has weather integrations but custom API calls with complex response parsing are much cleaner in Node-RED.
Voice command pipeline: HA sends voice assistant input to a Node-RED flow via event. Node-RED parses the natural language (optionally via a local LLM), maps it to a HA service call. Roll your own voice assistant without a cloud dependency.
Notification routing: Depending on time of day, who’s home, and notification severity — route alerts to different channels (phone notification during day, email overnight, silent during meeting hours).
Node-RED Persistent Context
Node-RED flows can store state between runs using context variables:
// In a function node
let count = context.get('doorbell_count') || 0;
count++;
context.set('doorbell_count', count);
if (count > 5) {
msg.payload = "Doorbell pressed excessively";
return msg;
}
return null; // Don't pass message further
This is how you implement rate limiting, counters, and state machines in Node-RED flows. HA’s template sensor can do some of this, but context storage in Node-RED is more flexible for complex logic.
The Home Assistant + Node-RED Workflow
The practical division of labor that works:
Use HA automations for:
- Simple trigger → action (sunset → turn on lights)
- Anything the UI automation editor handles in a few clicks
- HA-native features (scenes, scripts, templates)
Use Node-RED for:
- Multi-step sequences with timing and conditions
- Complex logic (more than 2-3 conditions)
- External API calls and response handling
- Loops and retry logic
- Anything where debugging matters
- Cross-cutting logic shared across multiple automations
The combination covers the full spectrum. HA handles device integration and simple automations. Node-RED handles the logic layer that would otherwise be spaghetti YAML.
Your hallway light at 3am problem: Node-RED flow, check binary_sensor.everyone_sleeping before triggering. Five minutes of flow editing. Done. The cat is now on its own.