Skip to content

Home Assistant on Raspberry Pi 5: NVMe Acceleration and 5 Real Incidents

I have had three Pi 5s in the homelab for Home Assistant over the last year. Two died. The third is still running because I fixed everything the first two did wrong. This is that playbook.

The quick-install guides get you to the HAOS login screen in eight minutes. They do not get you through a summer, a brownout, or an overnight OTA. The gap between "the logo appears" and "the machine runs unattended for a year" is where most of the real work is.

Why Pi 5 specifically

The Pi 5 is the first Raspberry board comfortable running a serious addon stack — Zigbee2MQTT, Mosquitto, Frigate, Nginx Proxy Manager, Vaultwarden — without feeling laggy. The quad-core Cortex-A76 at 2.4GHz is roughly 3x the single-threaded performance of the Pi 4B.

But it was also redesigned in ways that caught people off guard. It moved to USB-C power delivery, added a proper PCIe Gen2 lane on the M.2 slot, and uses a more aggressive power budget than any prior Pi. Each redesign introduced a new failure mode. Two killed my first Pi 5.

Hardware triptych: the three traps

1. The active cooler goes top face down

The Pi 5 active cooler is a single-bladed fan glued to a small aluminum heat sink. It clicks onto the top of the board, covering the SoC. There is only one correct orientation.

The #1 beginner mistake is installing the cooler on the bottom of the board. The official case clips only lock from the top, so the case prevents the error — but a bare board allows it. Backwards, the fan pulls air from the desk, passes it through the heat sink, and pushes it back into the desk. The SoC sits on top with no airflow over it and throttles within 30 minutes under load.

Fix: fan toward the SoC, heat sink outward, case clips engage from the top.

2. The PSU is 5V/5A, not 5V/3A

Pi 5 draws up to 5A at 5V under load — 25W before the NVMe. A random USB-C phone charger delivers 2-3A, enough to boot HAOS but not enough to survive a day of automation runs. Under load you will see:

  • The under-voltage symbol (red lightning bolt) in the console.
  • Random SD card corruption during writes.
  • NVMe drives silently dropping (dmesg | grep "link down").
  • Full reboots at random times during the day.

Fix: use the official Raspberry Pi 27W USB-C PSU or a certified 5V/5A PD brick. A cheap 45W Dell or Lenovo laptop brick works fine. Do not use a phone charger or a 3A wall-wart.

3. The PCIe lane is shared with USB4

The Pi 5 has a single PCIe Gen2 x1 lane. That lane serves both the M.2 slot and the internal USB4 hub. You get both, but not both at full speed. Plugging a USB3 SSD or USB3 network adapter into the USB4 port while the NVMe sits on M.2 causes both to negotiate down to Gen1, halving the theoretical bandwidth of each. HAOS barely notices — you are nowhere near the ceiling — but if you are measuring NVMe speed with fio or iostat, make sure nothing else is on the shared lane.

NVMe acceleration: real iostat numbers

On HAOS with a Kingston SN770 1TB via the official M.2 HAT, iostat -x 1 at rest versus during a Vaultwarden backup:

Rest (idle HAOS, no automations):

Device     r/s  wr/s  rkB/s  wkB/s  await r_await w_await  %util
nvme0n1    0.00  0.20    0.1    1.0   0.40    0.40    0.40   0.00

During a Vaultwarden vault export:

Device     r/s  wr/s  rkB/s  wkB/s  await r_await w_await  %util
nvme0n1    2.10 24.50   12.8  98.2   1.20    1.40    1.00  25.00

Peak write during a Frigate snapshot burst: ~180 MB/s sustained. Peak read during a full DB vacuum: ~420 MB/s. Both well within Gen2 x1 (theoretical ~985 MB/s, practical ~650 MB/s).

For comparison, a SanDisk High Endurance 32GB SD card on the same Pi 5 maxes out at ~25 MB/s writes and ~60 MB/s reads — a 7x difference on writes. That is why addon installs, MQTT broker logs, and Vaultwarden encryption all feel snappier on NVMe.

Cold boot times, power-off to HA login screen:

Boot source Cold boot Warm reboot
SD only (SanDisk High Endurance 32GB) 87s 61s
NVMe (SN770 1TB), SD as secondary 61s 34s
NVMe only, SD removed 24s 14s

87 seconds is "coffee's ready"; 24 seconds is "already done." The recorder DB startup — where HAOS loads the SQLite history into memory — drops from 12 seconds on SD to under 2 seconds on NVMe. That is the window where every history-touching automation would otherwise block.

Install path

Rufus on Windows, dd on Linux, Balena Etcher anywhere. Write the HAOS image for Raspberry Pi 5 64-bit directly to the SD, letting the tool handle alignment. Do not write a raw .img — HAOS expects a properly partitioned block device.

First boot is SD only. SSH in as root and confirm the drive is being seen at the PCIe layer:

sudo apt update && sudo apt install nvme-cli lspci
sudo nvme list
sudo lspci -vvv | grep -A2 M.2

If nvme list shows the drive but lspci reports Gen1 (Speed 2.5GT/s), the adapter is Gen1-only and bandwidth is halved. If nvme list shows nothing, the drive is not NVMe or the adapter is dead — check the spec sheet for "NVMe" versus "SATA", the two look identical on the shelf.

Format ext4, re-image, and let HAOS migrate:

sudo nvme format /dev/nvme0n1 --format-only --ses=1

Re-flash the NVMe with the same HAOS write tool. HAOS detects the second boot source on next power-up and offers to migrate /data. Accept, pull the SD, and the Pi 5 runs from NVMe with the SD slot free for cold-spares.

Incident 1: Thermal throttling under Frigate load

Second Pi 5, running Frigate with four RTSP cameras. Fine for two weeks, then one night I woke up to "camera stream unavailable" alerts.

vcgencmd measure_temp returned 92.3°C. vcgencmd get_throttled returned 0x50000 — thermal throttle plus under-voltage from the rail starving itself.

Root cause: the active cooler was installed correctly, but a USB3 wireless adapter on top of the case was lifting the cooler 4mm off the SoC and killing airflow.

Fix: removed the wireless adapter, added a second 40mm fan blowing across the passive cooler on the bottom of the board. Resting temp went from 48°C to 41°C. Ran another 6 months without a throttle event.

Incident 2: Brownout corrupting the SD card

Third Pi 5, my first attempt, died on day 4. I used a random 20W USB-C brick from the drawer.

Day 3: HAOS UI laggy during motion-triggered automations. Day 4: full reboot at 3:17am, SD card mount never recovered. Booting from a fresh SD and mounting the old one on another Pi showed a corrupt block table — unreadable on any reader.

Root cause: the 20W brick could not hold 5A. Under Frigate + Vaultwarden it dropped to 4.4V, tripping Pi 5's under-voltage protection. Pi 5 does not gracefully handle under-voltage during writes — it just stops, leaving the block table half-flushed.

Fix: bought the official 27W PSU and moved all critical storage to the NVMe.

Incident 3: NVMe not detected after first install

Used Kingston A400 M.2 2280 from a laptop, Hailo M.2 HAT. Nothing showed up when HAOS booted.

lsblk showed no /dev/nvme0n1. dmesg | grep -i nvme returned nothing — the controller was not enumerating. lspci showed the M.2 slot present but no responding drive.

Root cause: the Kingston A400 is SATA-based M.2 2280 — same form factor, different protocol. Pi 5's M.2 slot is NVMe-only and will not accept a SATA M.2 drive, ever, and there is no BIOS setting to change.

Fix: returned the A400, bought a Kingston SN770 (true NVMe), drive appeared on first boot. Always check "NVMe" versus "SATA" in the spec sheet — they look identical on the shelf.

Incident 4: Addon crashes after overnight OTA

Installed HA Core 2025.10 on a Sunday at 2am. HA rebooted at 2:14am. At 2:30am three addons failed to start: Zigbee2MQTT, Mosquitto, Frigate.

All three crashed with Error: Unable to import module. The OTA had also upgraded the Supervisor from 2025.09 to 2025.10. Three addons I had installed from third-party repos (not the official Marketplace) had no compatible 2025.10 release and their Docker images were yanked.

Fix: reinstalled each from the official Marketplace, one at a time. Zigbee2MQTT needed a config migration (serial_port → serial_port_path), which the migration tool did automatically.

Lesson: if you use third-party addons, disable automatic OTA for addons. Do addon updates during a window when you are awake and can catch breakage.

Incident 5: Silent backup failure for three weeks

The nastiest. HAOS had been running "scheduled backup to local /backup every 24 hours" for three weeks. On the fourteenth attempt I noticed the backup file was 40KB and dated three weeks ago.

  • ls -la /backup/ — file present, last modified 21 days ago.
  • Supervisor log showed the job running daily, "success" reported.
  • The "success" was a no-op. The path /backup/haos-backup.tgz existed and the job was configured to "overwrite if exists". The file was owned by root, the backup service ran as homeassistant, and homeassistant could not truncate a root-owned file. Every day, the job started, saw an unwritable file, silently reported success, and exited.

Fix: chown homeassistant:homeassistant /backup/haos-backup.tgz, deleted the stale file, next backup produced a real 1.2GB tarball.

Lesson: HAOS backup "success" is only meaningful if the file's mtime and size change. Add a cronjob on the Pi (visudo -f /etc/sudoers.d/backup-check) that alerts you if the backup has not grown in 24 hours. This class of silent failure is not documented anywhere.

Pi 5 vs Pi 4 vs J4125

All three are running Home Assistant right now for different purposes. Numbers below are from real installs with the same addon stack (HA Core 2025.10, Zigbee2MQTT, Mosquitto, Frigate with 4 cameras, Vaultwarden).

Metric Pi 5 (4GB + NVMe) Pi 4 (4GB + NVMe) J4125 (8GB + NVMe)
Idle CPU temp 42°C 38°C 35°C
Frigate 4-cam CPU temp 71°C (throttles at 90) 68°C 48°C
Vaultwarden encryption (250KB vault) 0.8s 2.1s 0.4s
Frigate detection latency (RTSP → event) 180ms 420ms 90ms
Sudden reboot under brownout Recovers in 40s Often corrupts SD Recovers in 25s
Silent Yes with active cooler Very quiet passively Very quiet passive case
Cost (used) $90 $55 $140 (mini-ITX)

Pi 4 is fine if you do not run Frigate — 3x slower than Pi 5 under sustained load, and no M.2 slot (USB3 NVMe enclosures work but add power draw). J4125 wins outright for anything involving computer vision or 24/7 sustained load — it simply does not throttle.

For pure home automation, Pi 4 is the cheapest correct answer. For Frigate plus a heavy addon stack, Pi 5 or J4125. For 8+ camera computer vision 24/7, J4125 or higher.

Conclusion

The Pi 5 is a great Home Assistant host if you respect three things: cooler orientation, PSU spec, and the shared PCIe lane. Ignore those and you will lose a board.

The five incidents above are not exotic. Every HAOS forum thread about "my Pi 5 keeps dying" traces back to one of them. Check all five boxes before you turn it on.