Send Home Assistant history somewhere that is not the SD card

Home Assistant's built-in influxdb integration can send history straight to Tag Historian — a block of YAML and a restart, nothing to install. If you would rather click than write YAML, there is also an optional Tag Historian custom component installed through HACS.

This page is the config, and then the four settings that decide whether it works. Before any of it: read whether you need external storage at all. For a lot of people the honest answer is no, and that page says so.

Last updated

What this actually does

Tag Historian speaks the InfluxDB v2 write protocol, which is exactly what Home Assistant's integration produces with api_version: 2. So Home Assistant thinks it is writing to an InfluxDB, and the data lands in an account in Azure Sweden Central instead of on the machine in your cupboard.

Numeric state is stored at full resolution for 14 days on Free, 6 months on Pro and 2 years on Business. After that window the individual readings are deleted and the hourly minimum, maximum, average and count stay for 10 years — on every plan, including the free one. See how long data is kept.

1. Get an API key

Create an account and an API key first. The free plan is €0 and takes an email address — no card — and gives you 5 tags and 50,000 readings a day. Then create the key on the Settings page in Tag Historian Explorer — and the scope you give it is not a detail.

The key is shown once. Copy it straight into Home Assistant’s secrets.yaml — if you lose it, generate a new one rather than hunting for the old one.

2. Put the key in secrets.yaml

secrets.yaml
taghistorian_api_key: <your-tag-historian-api-key>

3. Add the integration to configuration.yaml

configuration.yaml
influxdb:
  api_version: 2
  host: api.taghistorian.com   # host only - no https://
  port: 443
  ssl: true
  token: !secret taghistorian_api_key
  organization: home           # required by HA, ignored by Tag Historian
  bucket: home                 # required by HA, ignored by Tag Historian
  precision: s
  max_retries: 3
  include:
    entities:
      - sensor.outdoor_temperature
      - sensor.indoor_temperature
      - sensor.energy_consumption
      - binary_sensor.heat_pump_running

Restart Home Assistant. Readings appear as sensor.outdoor_temperature and so on within a minute or two.

The four lines that matter

1. include.entities — or Home Assistant sends everything

By default the integration ships every state change of every entity — every sensor, every automation toggle, every device tracker. Each distinct entity becomes one Tag Historian tag, and the free plan includes 5. An unfiltered Home Assistant burns through that in the first second, and every entity past the quota is refused with 422. Tags that already exist keep writing.

So filter at the source. The integration supports domains, entities and globs:

configuration.yaml
  include:
    domains: [sensor]
    entity_globs: ["sensor.*_temperature"]
    entities: [binary_sensor.heat_pump_running]

An entity listed under include.entities always wins over any exclude rule. The safest shape is the one in the config above: an explicit list of exactly the entities you want history for, and nothing else.

2. max_retries: 3 — because the default is 0

Home Assistant's default is no retries, and it never reads the Retry-After header. With the default, a batch that meets a daily quota (429) or a brief interruption (503) is thrown away and the run moves on — that data is gone. max_retries: 3 makes the integration re-attempt on its own schedule, which rides out short interruptions in practice. It still cannot wait out a daily quota: data sent while hard over quota is dropped by Home Assistant once its retries run out.

3. A numeric entity costs one tag. A non-numeric one costs several

Home Assistant sends the entity's state and every one of its attributes on the same line. What that costs depends on the state. If the state is a number — or one of the on/off pairs Home Assistant converts, like on/off and home/not_home — it arrives in the line's value field, Tag Historian stores that and ignores every attribute beside it. One entity, one tag: sensor.outdoor_temperature. That is the normal case and it is what the include list above is made of.

If the state is not a number — a climate entity sitting at heat, a weather entity at cloudy — there is no value field on that line, so every numeric attribute becomes its own tag instead, named {entity}.{attribute}. A single climate.living_room produces climate.living_room.current_temperature, climate.living_room.temperature, climate.living_room.min_temp, climate.living_room.max_temp and more — several tags from one line in your include list, most of them constants that never change.

So keep include.entities to entities whose state is a number. If you want one attribute of a non-numeric entity, create a template sensor that exposes it as its own entity: one tag with a name you chose, instead of six you did not.

One more thing about naming: leave out a static tags: block. Extra tags get appended to the series name, so sensor.outdoor_temperature becomes sensor.outdoor_temperature.instance-home2. That is useful on purpose — two Home Assistant instances writing the same entity stay two distinct series — but it is a surprise if you did not mean it.

4. unknown and unavailable never arrive

Home Assistant does not send non-numeric states, so a sensor that goes unavailable simply stops producing points. A gap in the chart means “Home Assistant had nothing numeric to say”, not that zeroes were stored. That matches how Tag Historian treats data everywhere: a missing reading is a gap, never an invented zero.

Reading the log

StatusWhat it means
204Everything was accepted.
400Empty body — the setup probe. One at startup is normal. Otherwise: an unparsable body or an invalid precision.
401Wrong or revoked API key.
403Email address not confirmed and the 7-day grace period has passed. Reading still works; confirm the address and writing resumes immediately.
422New entities would exceed your tag quota, so those points were dropped. Existing tags were still written.
429Daily readings quota reached. Retry-After says when to come back.
503Temporarily unavailable, with Retry-After — never a silent drop.

The full table, including the storage-quota and payload-size cases, is on the line protocol reference.

How many tags will you actually need?

The arithmetic nobody publishes: a tag is a series, not a reading. A sensor polled every ten seconds and a sensor polled once an hour cost the same, because the price follows the number of series and not the sample rate. What that means per plan:

PlanEntitiesReadings/dayThat is roughly
Free550,0005 entities, each once every 10 seconds, all day
Pro50500,00050 entities, each once every ~8.6 seconds
Business5005,000,000500 entities, each once every ~8.6 seconds

The daily allowance is a shared budget rather than a per-tag rate, so you can spend it on breadth or on frequency: Pro's 500,000 is 50 entities at ~8.6 seconds, or 10 entities at ~1.7 seconds.

What this is not

  • It is not a replacement for the recorder. Home Assistant still keeps its own database and still draws its own charts from it. This is a copy that outlives the box.
  • It does not read back into Home Assistant. There is no query API and no Flux — data comes out through the Tag Historian API, its charts, and exports to CSV, JSON or Parquet.
  • Strings are not stored. Only numbers, and booleans as 1 and 0.

Running Telegraf instead?

Telegraf writes to the same endpoint with its stock outputs.influxdb_v2. That is a separate page, mostly because Telegraf's default inputs will eat your tag quota in a way Home Assistant's will not.

Endpoint for both: https://api.taghistorian.com

Common questions

How do I keep Home Assistant history for longer than 10 days?
Home Assistant's recorder purges after 10 days by default, but its long-term statistics table keeps hourly min, max and mean forever for any entity that has a state_class — locally, for free. You only need external storage if you want full resolution beyond 10 days, if the entity has no state_class, or if you want the history to survive the machine. Home Assistant's built-in influxdb integration can write to any InfluxDB v2 endpoint, including Tag Historian.
Do I need to install anything in Home Assistant?
Nothing is required. The influxdb integration ships with Home Assistant — a block of YAML in configuration.yaml and a restart. There is also an optional Tag Historian custom component, installed through HACS — see taghistorian.com/docs/home-assistant-hacs for the picker, the live tag quota and the Repairs diagnostics it adds. Both paths are fully supported.
Does one Home Assistant entity count as one tag?
When its state is a number, yes: the entity becomes one tag named {domain}.{entity_id} — for example sensor.outdoor_temperature. An entity whose state is not a number, like a climate entity sitting at "heat", has no numeric state to store, so each of its numeric attributes becomes a tag of its own instead — several tags from one entity. The free plan includes 5 tags, so the include.entities filter is required reading, and it should name entities whose state is numeric.
Are entity attributes stored?
Not when the state itself is a number — then only the state is stored and the attributes are ignored. When the state is not a number there is nothing else to store, so every numeric attribute becomes its own tag. To keep one specific attribute as history, expose it as its own template sensor in Home Assistant, which costs one tag with a name you chose.

Try it on the free plan

5 tags, 50,000 readings a day, 14 days at full resolution and ten years of hourly summaries. €0, no card.