<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>InfluxData Blog - Developer</title>
    <description>Posts from the Developer category on the InfluxData Blog</description>
    <link>https://www.influxdata.com/blog/category/tech/</link>
    <language>en-us</language>
    <lastBuildDate>Fri, 23 Oct 2026 08:00:00 +0000</lastBuildDate>
    <pubDate>Fri, 23 Oct 2026 08:00:00 +0000</pubDate>
    <ttl>1800</ttl>
    <item>
      <title>Data Center Telemetry in the AI Era</title>
      <description>&lt;p&gt;A decade ago, a typical enterprise rack drew five to ten kilowatts and was cooled by air. Today, reference designs for liquid-cooled AI racks run up to 132 kW per rack, and a large training cluster can swing a facility’s power draw by megawatts in a few seconds. More than half of operators in &lt;a href="https://uptimeinstitute.com/resources/research-and-reports/uptime-institute-global-data-center-survey-results-2026"&gt;Uptime Institute’s 2026 survey&lt;/a&gt; built or upgraded high-density space in the past year, and 70% plan to in the next year as well. The entire industry is changing as AI-focused workloads become more common.&lt;/p&gt;

&lt;p&gt;Telemetry is how operators see what all that hardware is doing. Most data centers already collect a great deal of it. The trouble is that this data lives in different systems, at different resolutions, with different clocks, owned by different teams. In a data center running AI workloads, where a cooling problem can surface as a slow training job, that fragmentation makes problems difficult to trace. Handling this new set of problems requires a different approach and different tools.&lt;/p&gt;

&lt;h2 id="what-is-data-center-telemetry"&gt;What is data center telemetry?&lt;/h2&gt;

&lt;p&gt;Data center telemetry is the continuous, time-stamped measurement of every layer of a data center, from the utility feed to the training job. It is used for three things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;: dashboards, threshold alerts, and on-call response&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automation&lt;/strong&gt;: actions taken on the data, like draining an unhealthy node or flagging a rack whose coolant flow is drifting&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Planning&lt;/strong&gt;: capacity, power provisioning, forecasting, hardware replacement, and contract evidence, all built on history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It helps to think of telemetry in seven layers. The first three belong to the facility (operational technology, or OT). The last four belong to the IT stack.&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Layer&lt;/th&gt;
    &lt;th&gt;Signals&lt;/th&gt;
    &lt;th&gt;Sources&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;Power&lt;/td&gt;
    &lt;td&gt;Utility feeds, switchgear, UPS state of charge and battery health, and PDU branch-circuit load&lt;/td&gt;
    &lt;td&gt;EPMS, power meters, SNMP, Modbus&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Cooling&lt;/td&gt;
    &lt;td&gt;Supply and return temperatures, chilled water, CDU flow, pressure, leak detection, coolant conductivity&lt;/td&gt;
    &lt;td&gt;BMS, SCADA&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Environment&lt;/td&gt;
    &lt;td&gt;Rack inlet temperature, humidity, differential pressure, airflow&lt;/td&gt;
    &lt;td&gt;Sensors, DCIM tools&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Compute&lt;/td&gt;
    &lt;td&gt;CPU, memory, fans, power supplies, firmware events&lt;/td&gt;
    &lt;td&gt;Host agents, BMC (Redfish, IPMI)&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Accelerators&lt;/td&gt;
    &lt;td&gt;GPU power, clocks, temperature, ECC errors, HBM row remapping, NVLink errors, XID events&lt;/td&gt;
    &lt;td&gt;NVIDIA DCGM&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Network&lt;/td&gt;
    &lt;td&gt;Port counters, congestion, pause frames, link flaps, InfiniBand error counters&lt;/td&gt;
    &lt;td&gt;gNMI streaming, SNMP, NVIDIA UFM, NetQ&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Workload&lt;/td&gt;
    &lt;td&gt;Job starts/ends, checkpoints, node drains, queue state&lt;/td&gt;
    &lt;td&gt;Slurm, Kubernetes&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;h2 id="how-ai-changed-data-center-telemetry"&gt;How AI changed data center telemetry&lt;/h2&gt;

&lt;p&gt;At AI rack power levels, air cooling stops being enough and liquid cooling becomes mandatory. That adds a new set of plumbing signals to watch like flow balance across compute trays, pressure drop across filters, coolant chemistry and hundreds of quick-disconnect fittings per rack.&lt;/p&gt;

&lt;p&gt;In a training job, thousands of GPUs work in lockstep. They alternate between compute-heavy and communication phases, and they pause together for checkpoints. Uptime Institute describes facility-scale load steps every few seconds, with checkpoints causing steep drops that recover tens of seconds later. &lt;a href="https://www.insurancejournal.com/news/international/2026/08/12/881044.htm"&gt;Bloomberg reported in August 2026&lt;/a&gt; that these swings are wearing out power and cooling equipment, including batteries and generators, far sooner than expected, with spikes as high as 50% above design capacity.&lt;/p&gt;

&lt;p&gt;At this scale, hardware failures are routine. During the Llama 3 training run,&lt;a href="https://ai.meta.com/research/publications/the-llama-3-herd-of-models/"&gt; Meta’s 16,384 GPU cluster saw 419 unexpected interruptions in 54 days&lt;/a&gt;, roughly every three hours.&lt;/p&gt;

&lt;p&gt;Slow hardware is even more common than failed hardware. Researchers studying clusters of more than 10,000 GPUs found that &lt;a href="https://arxiv.org/html/2410.12588v1"&gt;59% of large training jobs experience “fail-slow” stragglers&lt;/a&gt;, with an average 34.6% longer time to completion.&lt;/p&gt;

&lt;p&gt;Taken together, these mean the cause of a problem and its symptoms often sit in different layers. A drifting coolant loop shows up as GPU throttling, and a flapping link shows up as a slow job. Without unifying your datal, you won’t be able to find the root cause of many of the problems you are facing.&lt;/p&gt;

&lt;h2 id="why-data-center-telemetry-is-a-hard-workload"&gt;Why data center telemetry is a hard workload&lt;/h2&gt;

&lt;p&gt;Eight main challenges repeatedly come up when trying to collect data center telemetry in a way that correlates the layers..&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/1L09hE5Fr5JNhiMTwuFMaY/6edbd3f4a3a944eababb7e7d47c07aab/fa82e13f-7e26-4e03-801c-2ad8ad58088c.png" alt="Data Center image 1" /&gt;&lt;/p&gt;

&lt;h4 id="protocol-sprawl"&gt;Protocol Sprawl&lt;/h4&gt;

&lt;p&gt;A single site might use SNMP, Modbus, BACnet, Redfish, IPMI, gNMI, OPC UA, MQTT, and Prometheus endpoints. Integrators routinely chain gateways to translate between them. Every translation hop is another place for data to get lost.&lt;/p&gt;

&lt;h4 id="high-cardinality-data"&gt;High-Cardinality Data&lt;/h4&gt;

&lt;p&gt;Every GPU ID, NVLink pair, switch port, circuit, and job adds tags, and every tag combination is a separate time series. In a &lt;a href="https://www.backend.ai/blog/engineering/2026-02-listening-to-500-plus-gpus-pulse"&gt;write-up on monitoring more than 500 GPUs&lt;/a&gt;, Backend.AI’s team found that a single GPU temperature metric produced 504 series, and some high-cardinality queries ran out of memory as a result.&lt;/p&gt;

&lt;h4 id="mismatched-resolution"&gt;Mismatched Resolution&lt;/h4&gt;

&lt;p&gt;Building management trends are often logged every one to 15 minutes, or only when a value changes. SNMP polling typically runs every 30 to 300 seconds. Prometheus scrapes and NVIDIA UFM’s default telemetry runs around every 30 seconds. AI power swings happen every few seconds, so a one-minute average can hide them completely.&lt;/p&gt;

&lt;h4 id="clock-drift"&gt;Clock Drift&lt;/h4&gt;

&lt;p&gt;When each system stamps data with its own clock, you can’t reliably line up a coolant excursion with a GPU throttling event after the fact. SNMP makes this worse, because values are usually time-stamped when they reach the collector, which can be some time after the measurement.&lt;/p&gt;

&lt;h4 id="ownership-of-systems"&gt;Ownership of Systems&lt;/h4&gt;

&lt;p&gt;Facilities own the BMS and EPMS; IT operations own DCIM and network monitoring; the GPU platform team owns DCGM and Prometheus; ML or research teams own the scheduler and job logs. Each system has its own alerts and history, and each was designed to answer its own team’s questions. This makes it hard to integrate all these different systems from both a technical and simple access perspective.&lt;/p&gt;

&lt;p&gt;The Backend.AI team notes that earlier research found ECC and NVLink errors were detected through CPU metrics more often than through GPU metrics. Before one NVLink failure on their own cluster, the earliest warning sign was an application task count on the affected node jumping to about 18 times its normal level. They concluded that no single metric type caught every failure, so you need coverage across layers.&lt;/p&gt;

&lt;h4 id="data-retention-costs"&gt;Data Retention Costs&lt;/h4&gt;

&lt;p&gt;Real-time monitoring needs recent, high-resolution data. Capacity planning, warranty claims, SLA disputes, and billing need months or years of it. Prometheus-style systems are excellent at recent data, but long retention at GPU fleet cardinality usually means bolting on another tier for historical data.&lt;/p&gt;

&lt;h4 id="data-collection"&gt;Data Collection&lt;/h4&gt;

&lt;p&gt;A large data center can run thousands of collection agents across GPU nodes, BMC networks, fabric collectors, and facility gateways. Each one needs proper configuration, including credentials and a suitable polling interval. Configuration drift across a fleet of agents becomes its own source of blind spots.&lt;/p&gt;

&lt;h4 id="security"&gt;Security&lt;/h4&gt;

&lt;p&gt;Facility control networks are segmented from IT for good reason. Facilities teams rarely let IT tools poll their PLCs or power meters directly, so telemetry usually comes through read-only paths like the BMS or EPMS itself, a historian, an OPC UA server, or an MQTT broker at the OT boundary.&lt;/p&gt;

&lt;h2 id="what-a-good-telemetry-architecture-looks-like"&gt;What a good telemetry architecture looks like&lt;/h2&gt;

&lt;p&gt;Whatever tools you choose as part of your tech stack, a few principles apply:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Collect from every layer, because the cause and the symptom are often in different places.
Put any data you need to correlate on one clock, in one store.&lt;/li&gt;
  &lt;li&gt;Match resolution to the signal. Collect GPU and rack power at around one second where it matters; most other signals are fine at 15 to 60 seconds.&lt;/li&gt;
  &lt;li&gt;Keep fast control local. Protective relays, UPS systems, rack power-smoothing hardware, GPU firmware, and CDU pump loops act in microseconds to milliseconds and should never depend on a database. Telemetry records what they did.&lt;/li&gt;
  &lt;li&gt;Store history in open formats, so analytics and ML teams can use it without exporting it first.&lt;/li&gt;
  &lt;li&gt;Manage collection as a fleet, with central configuration in place of hand-edited files on individual hosts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How fast each control loop runs decides where a telemetry platform fits.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/6qOwr01AhpuJCUDBdqM58L/223752e7dbda38026a1987d6d7b4e5e2/07fa0817-5d47-4c87-b7a5-e8d85687ffd9.png" alt="Data Center image 2" /&gt;&lt;/p&gt;

&lt;p&gt;The first two tiers, protecting and stabilizing, belong to hardware and dedicated controllers. A telemetry platform supplies the history that shapes their policies, but it is not in their loop.&lt;/p&gt;

&lt;p&gt;From seconds upward, telemetry takes over. Automation can act within seconds to minutes, for example by draining and requeueing an unhealthy node or flagging a fail-slow GPU. Over longer periods, cooling setpoint optimizers read telemetry every few minutes and recommend changes—which local control systems check before anything happens—and months of history drive capacity planning and hardware replacement.&lt;/p&gt;

&lt;h2 id="how-telegraf-and-influxdb-3-fit-into-a-data-center-telemetry-architecture"&gt;How Telegraf and InfluxDB 3 fit into a data center telemetry architecture&lt;/h2&gt;

&lt;h4 id="telegraf"&gt;Telegraf&lt;/h4&gt;

&lt;p&gt;Telegraf is an open source collection agent with more than 400 plugins. It works alongside your existing tools: it collects from the same exporters your GPU team already runs, and it reads facility data over read-only paths without polling control equipment directly. Because every source goes through the same agent, every data point arrives with consistent tags and timestamps.&lt;/p&gt;

&lt;p&gt;These are the plugins most useful in a data center:&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Layer&lt;/th&gt;
    &lt;th&gt;Telegraf plugin&lt;/th&gt;
    &lt;th&gt;Collects from&lt;/th&gt;
    &lt;th&gt;Why it matters&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;Accelerators&lt;/td&gt;
    &lt;td&gt;Prometheus&lt;/td&gt;
    &lt;td&gt;NVIDIA DCGM exporter, plus other exporters such as UFM's&lt;/td&gt;
    &lt;td&gt;Reuses the GPU metrics the platform team already exposes, so there is no second GPU agent to run&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Accelerators&lt;/td&gt;
    &lt;td&gt;NVIDIA SMI&lt;/td&gt;
    &lt;td&gt;GPUs directly, through nvidia-smi&lt;/td&gt;
    &lt;td&gt;A simple option for smaller clusters that don't run DCGM&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Compute&lt;/td&gt;
    &lt;td&gt;Redfish&lt;/td&gt;
    &lt;td&gt;Server BMCs&lt;/td&gt;
    &lt;td&gt;Health, power, temperature and fan data from the management controller, even when the operating system is down&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Compute&lt;/td&gt;
    &lt;td&gt;IPMI Sensor&lt;/td&gt;
    &lt;td&gt;Older BMCs&lt;/td&gt;
    &lt;td&gt;Covers servers that predate Redfish&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Network&lt;/td&gt;
    &lt;td&gt;gNMI&lt;/td&gt;
    &lt;td&gt;Ethernet switches that stream telemetry&lt;/td&gt;
    &lt;td&gt;Captures short congestion bursts and link flaps that slower polling misses&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Network and power&lt;/td&gt;
    &lt;td&gt;SNMP&lt;/td&gt;
    &lt;td&gt;PDUs, UPS systems, older switches, environmental sensors&lt;/td&gt;
    &lt;td&gt;The protocol nearly all existing data center hardware speaks&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Power and cooling&lt;/td&gt;
    &lt;td&gt;Modbus&lt;/td&gt;
    &lt;td&gt;Power meters and CDUs, directly or through protocol gateways&lt;/td&gt;
    &lt;td&gt;Reads the industrial devices common in electrical and mechanical rooms&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Power and cooling&lt;/td&gt;
    &lt;td&gt;OPC UA&lt;/td&gt;
    &lt;td&gt;Facility systems such as the BMS or a historian&lt;/td&gt;
    &lt;td&gt;A read-only path to facility data that respects the OT network boundary&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Facility&lt;/td&gt;
    &lt;td&gt;MQTT Consumer&lt;/td&gt;
    &lt;td&gt;Facility message brokers and IoT sensors&lt;/td&gt;
    &lt;td&gt;Subscribes to data the facility side already publishes&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Workload&lt;/td&gt;
    &lt;td&gt;Slurm and Kubernetes&lt;/td&gt;
    &lt;td&gt;Job schedulers and clusters&lt;/td&gt;
    &lt;td&gt;Adds job and node state, so problems can be tied to the work they affect&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Any layer&lt;/td&gt;
    &lt;td&gt;OpenTelemetry&lt;/td&gt;
    &lt;td&gt;Existing OpenTelemetry collectors&lt;/td&gt;
    &lt;td&gt;Brings in data from pipelines teams already run, without changing them&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Telegraf can then write everything to InfluxDB 3 or another database of your choice.&lt;/p&gt;

&lt;h4 id="telegraf-controller-run-data-collection-as-a-fleet"&gt;Telegraf Controller: run data collection as a fleet&lt;/h4&gt;

&lt;p&gt;Telegraf Controller is a control plane for Telegraf agents. Agents pull their configurations from it, and operators get one view of the whole fleet. Configuration templates cover each layer (GPU nodes, BMC collectors, fabric collectors, and facility gateways). Staged rollouts let changes reach one rack or hall before every site, and agent health checks and drift detection catch broken or misconfigured agents before they leave a blind spot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.influxdata.com/blog/influxdata-announces-telegraf-enterprise-ga/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=data_center_telemetry&amp;amp;utm_content=blog"&gt;Telegraf Enterprise&lt;/a&gt; adds support for tens of thousands of agents, unlimited configurations, audit logging, LDAP/OIDC, and commercial support. The &lt;a href="https://www.influxdata.com/blog/whats-new-in-influxdb-telegraf-q2-2026-product-updates/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=data_center_telemetry&amp;amp;utm_content=blog"&gt;free Controller tier&lt;/a&gt; covers up to 100 agents and 20 configurations.&lt;/p&gt;

&lt;p&gt;Telegraf Controller also lets you set collection resolution per rack or per job. Collecting every signal at one second is expensive. With templates and staged rollouts, you can push a one-second power and GPU profile to the racks running a large training job, or to a rack you’re investigating, and roll it back when you’re done.&lt;/p&gt;

&lt;h4 id="influxdb-3"&gt;InfluxDB 3&lt;/h4&gt;

&lt;p&gt;InfluxDB 3 is built for high-cardinality, high-resolution time series data, so per-GPU, per-port, per-circuit and per-job series can live together without being trimmed to fit. You query it with SQL or InfluxQL. GPU and facility data can sit in separate databases, owned by separate teams, and still be queried together.&lt;/p&gt;

&lt;p&gt;Data is stored in object storage, which keeps long-term history inexpensive and lets lakehouse and ML tools read it directly. InfluxDB 3 can be run self-hosted, which matters for on-premises and air-gapped AI sites where SaaS monitoring isn’t an option.&lt;/p&gt;

&lt;p&gt;The Processing Engine runs Python code inside the database, either on a schedule or as new data arrives. That makes it a natural fit for the response tier: checks and automation that need to run within seconds to minutes, next to the data.&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Processing Engine feature&lt;/th&gt;
    &lt;th&gt;What it does&lt;/th&gt;
    &lt;th&gt;How it helps in a data center&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;Data write triggers&lt;/td&gt;
    &lt;td&gt;Runs code as soon as new data is written to a table&lt;/td&gt;
    &lt;td&gt;React to a GPU error event or a leak-sensor reading as it arrives, without waiting for the next dashboard refresh&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Scheduled triggers&lt;/td&gt;
    &lt;td&gt;Runs code at a fixed interval or on a cron schedule&lt;/td&gt;
    &lt;td&gt;Compare each GPU with the others in its node every 30 seconds to catch fail-slow hardware, or produce daily health reports&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;HTTP request triggers&lt;/td&gt;
    &lt;td&gt;Exposes a plugin as an HTTP endpoint&lt;/td&gt;
    &lt;td&gt;Lets other tools, such as a scheduler or a runbook, ask for a node's health status on demand&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Results written back as data&lt;/td&gt;
    &lt;td&gt;Plugins store their findings as new time series&lt;/td&gt;
    &lt;td&gt;Health flags can feed alerts and dashboards from one source, and an automation script can turn them into drain requests to Slurm or Kubernetes&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Trigger arguments&lt;/td&gt;
    &lt;td&gt;Passes settings, such as thresholds, when a trigger is created&lt;/td&gt;
    &lt;td&gt;Tune the same check per cluster or hardware generation without changing code&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Plugin Library&lt;/td&gt;
    &lt;td&gt;Ready-made plugins for common tasks such as downsampling and alerting&lt;/td&gt;
    &lt;td&gt;Get started without writing code, and downsample high-resolution data for long-term retention&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Python packages&lt;/td&gt;
    &lt;td&gt;Plugins can use standard Python libraries&lt;/td&gt;
    &lt;td&gt;Use familiar statistics and anomaly-detection libraries for trend and drift checks&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/4lMp5NZljYhxgowwboltU5/54bba76e5f365d5bc9619681bc51b478/42bff882-c496-4141-a303-2cfc838715bf.png" alt="Data Center image 3" /&gt;&lt;/p&gt;

&lt;h2 id="data-center-telemetry-use-cases"&gt;Data center telemetry use cases&lt;/h2&gt;

&lt;h4 id="connecting-power-swings-to-training-jobs"&gt;Connecting Power Swings to Training Jobs&lt;/h4&gt;

&lt;p&gt;With power data from the GPUs up to the UPS in the same store as job and checkpoint events, you can see which jobs produce which load steps, and how often they cycle the batteries. Facilities and platform teams then have a shared, factual starting point for tuning power smoothing, power capping, checkpoint timing, or job placement.&lt;/p&gt;

&lt;h4 id="retiring-gpus-before-they-fail"&gt;Retiring GPUs Before They Fail&lt;/h4&gt;
&lt;p&gt;In the Llama 3 run, 30.1% of interruptions were caused by GPU faults (including NVLink) and 17.2% by HBM3 memory. Trending memory errors (ECC errors and row-remapping counts) and HBM temperature per GPU over several weeks produces a short list of devices to pull at the next maintenance window, before they take down a job running across thousands of GPUs. The same history becomes evidence for RMA (return) claims.&lt;/p&gt;

&lt;h4 id="catching-liquid-cooling-drift"&gt;Catching Liquid-Cooling Drift&lt;/h4&gt;

&lt;p&gt;Liquid loops tend to degrade slowly before anything trips an alarm. Trending the worst-flowing branch, filter pressure drop, pump effort, and coolant conductivity, and alerting on rate of change rather than absolute limits, turns a surprise outage into a scheduled repair.&lt;/p&gt;

&lt;h4 id="settling-sla-and-billing-questions"&gt;Settling SLA and Billing Questions&lt;/h4&gt;

&lt;p&gt;When facility and GPU timelines sit in one store, a colocation provider and its tenant can check whether a GPU slowdown started with a cooling event in the hall or inside the tenant’s own hardware. The same records help reconcile power billed per circuit with GPU usage billed per job.&lt;/p&gt;

&lt;h2 id="getting-started-with-influxdb-and-telegraf-for-data-center-telemetry-workloads"&gt;Getting started with InfluxDB and Telegraf for data center telemetry workloads&lt;/h2&gt;

&lt;p&gt;Most data centers are already collecting the telemetry data they need, but it isn’t available in a way that maximizes its value. As you’ve seen in this article, Telegraf and InfluxDB 3 are valuable tools for solving a number of common problems seen in data centers. Check out the resources below to get started.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.influxdata.com/influxdb-signup/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=data_center_telemetry&amp;amp;utm_content=blog"&gt;Get started with InfluxDB 3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.influxdata.com/products/telegraf-enterprise/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=data_center_telemetry&amp;amp;utm_content=blog"&gt;Get Started with Telegraf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="faq"&gt;FAQ:&lt;/h2&gt;

&lt;div id="accordion_second"&gt;
    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-1"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;Why is telemetry harder in AI data centers?
&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-1" class="message-body is-collapsible is-active" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
               AI racks draw far more power and usually need liquid cooling, which adds a new set of signals to watch. Training jobs run thousands of GPUs in lockstep, so problems spread quickly and power draw can swing sharply within seconds. At this scale, hardware failures are routine, and slow GPUs and links are more common still. As a result, the cause of a problem and its symptoms often sit in different systems.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-2"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;Do I need to replace Prometheus or NVIDIA DCGM to use InfluxDB 3?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-2" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                No. Many GPU platform teams already run DCGM with Prometheus, and they can keep it. Telegraf can collect from the same DCGM exporter, and InfluxDB 3 adds facility data and long-term history in the same store.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-2"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;What is the difference between data center telemetry and data center monitoring?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-2" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Telemetry is the data: continuous, time-stamped measurements from power, cooling, servers, GPUs, the network, and workloads. Monitoring is one thing you do with that data, such as dashboards and alerts. The same telemetry also drives automation, like draining an unhealthy node, and planning, like deciding how much power capacity a new cluster needs.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

&lt;/div&gt;
</description>
      <pubDate>Fri, 23 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/data-center-telemetry/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/data-center-telemetry/</guid>
      <category>Developer</category>
      <category>Use Cases</category>
      <author>Charles Mahler (InfluxData)</author>
    </item>
    <item>
      <title>Root Cause Analysis Workflows Using InfluxDB </title>
      <description>&lt;p&gt;It’s 2:00 AM, and your monitoring system fires a critical alert. Latency is spiking, and overseas users are registering internal server error complaints.&lt;/p&gt;

&lt;p&gt;How quickly can you find the root problem? Your logs and relational databases hold plenty of data about what’s happening. But it’s difficult, if not downright impossible, to coerce that information into a timeline that will help you figure out what’s happening.&lt;/p&gt;

&lt;p&gt;Establishing an accurate sequence of events is a key step in root cause analysis (RCA), and that’s where InfluxDB comes in. It excels at collecting, storing, and querying high-resolution, time-stamped metrics.&lt;/p&gt;

&lt;p&gt;These abilities make InfluxDB the ideal tool for reconstructing the scene of an operational crime and finding the definitive cause of an incident. Let’s see how.&lt;/p&gt;

&lt;h2 id="what-is-root-cause-analysis"&gt;What is Root Cause Analysis?&lt;/h2&gt;

&lt;p&gt;Before we start, let’s make sure we’re all on the same page. __Root cause analysis is a structured methodology for identifying the core cause of an issue, failure, or unexpected event. __&lt;/p&gt;

&lt;p&gt;RCA uncovers why a problem occurred in the first place, ensuring you can prevent it from happening again.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It’s not uncommon for the components in a distributed system to literally and figuratively speak different languages.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="time-series-data-is-the-foundation-of-rca"&gt;Time series data is the foundation of RCA&lt;/h2&gt;

&lt;p&gt;It’s not uncommon for the components in a distributed system to literally and figuratively speak different languages. Your API gateway might be written in Go, while you’re using an off-the-shelf authorization service that’s implemented in Node.js.&lt;/p&gt;

&lt;p&gt;At the same time, you might have a mix of backend workers running in &lt;a href="https://docs.influxdata.com/influxdb/v2/api-guide/client-libraries/python/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=root_cause_analysis_workflows_influxdb&amp;amp;utm_content=blog"&gt;Python&lt;/a&gt; and &lt;a href="https://docs.influxdata.com/influxdb3/core/reference/client-libraries/v3/java/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=root_cause_analysis_workflows_influxdb&amp;amp;utm_content=blog"&gt;Java&lt;/a&gt;. So when a critical incident strikes, they’re logging messages in different languages, using different terminology, and generating stack traces that look like they’re from different worlds.&lt;/p&gt;

&lt;p&gt;But no matter how many dialects your services speak, they share one property you can take advantage of: time. Causality is the key to RCA. You need to prove that event A caused event B. When time is the anchor, you’re halfway there.&lt;/p&gt;

&lt;p&gt;So how do you view events from more than one service? Use InfluxDB as your central telemetry hub. Logs tell you what happened. Traces give you part of why it happened. InfluxDB tells you when and in what sequence you can tie these‌ events together.&lt;/p&gt;

&lt;h2 id="a-root-cause-analysis-workflow"&gt;A Root Cause Analysis workflow&lt;/h2&gt;

&lt;p&gt;Let’s examine a four-step workflow that uses time series data and InfluxDB to perform root cause analysis.&lt;/p&gt;

&lt;h4 id="establish-the-outage-horizon-isolate-the-timeline"&gt;Establish the Outage Horizon (Isolate the Timeline)&lt;/h4&gt;

&lt;p&gt;When you receive a critical alert, your first instinct might be to delve into the data. If an app generated the message, you might jump right into the code. If it came from &lt;a href="https://www.influxdata.com/solutions/infrastructure-and-application-monitoring/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=root_cause_analysis_workflows_influxdb&amp;amp;utm_content=blog"&gt;infrastructure&lt;/a&gt;, you might start by examining logs and tweaking configurations.&lt;/p&gt;

&lt;p&gt;Don’t do that.&lt;/p&gt;

&lt;p&gt;Before you can figure out why something happened, you need to establish exactly when it started.&lt;/p&gt;

&lt;h4 id="identify-t-0-the-exact-moment-of-impact"&gt;Identify T-0: The Exact Moment of Impact&lt;/h4&gt;

&lt;p&gt;Every incident has a definitive starting point: the millisecond the system transitioned from healthy to degraded. This is your T-0, and you identify it by looking at the metric that triggered the alert. So, in the example above, you’d be looking for the leading edge of that spike in latency.&lt;/p&gt;

&lt;p&gt;You might be tempted to look back at the trigger for spikes in CPU utilization or disk I/O. But that’s moving the goalposts.&lt;/p&gt;

&lt;p&gt;The event was an increase in latency, and you’re trying to identify the root cause. You may look at those metrics later, and you may learn you need to set up new alerts for them. But you’re not there yet.&lt;/p&gt;

&lt;p&gt;First, use InfluxDB to zoom in on where the trend abruptly changes direction. That exact second or millisecond is an anchor point.&lt;/p&gt;

&lt;p&gt;Whatever caused the problem must have occurred at, or immediately before, this timestamp. Any event, error, or metric shift after T-0 is a symptom, not a trigger.&lt;/p&gt;

&lt;p&gt;*Alt text: A sudden spike in latency doesn’t mean much unless you can contrast it with what was normal before the problem. *&lt;/p&gt;

&lt;h4 id="define-your-window"&gt;Define Your Window&lt;/h4&gt;

&lt;p&gt;After you’ve identified T-0, add some context. A sudden spike in latency doesn’t mean much unless you can contrast it against what was normal before the problem occurred.&lt;/p&gt;

&lt;p&gt;So, establish your investigation window by zooming out and capturing thirty to sixty minutes of data before T-0.&lt;/p&gt;

&lt;p&gt;This window represents your baseline. By framing your InfluxDB queries to include this buffer, you map out the contrast between a healthy system and a failing one. You’re looking for clues that started before the problem.&lt;/p&gt;

&lt;p&gt;So, now it’s time to look at those other metrics.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Was CPU utilization creeping up before the crash?&lt;/li&gt;
  &lt;li&gt;Did database response times start spiking prior to the alert?&lt;/li&gt;
  &lt;li&gt;Is there a deployment or feature-flag toggle leading up to the event?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This takes us to the next step.&lt;/p&gt;

&lt;h4 id="correlate-the-four-golden-signals"&gt;Correlate the Four Golden Signals&lt;/h4&gt;

&lt;p&gt;Now that you’ve defined your window, you can overlay latency, traffic, errors, and saturation to see how they interact. Here’s where &lt;a href="https://www.influxdata.com/products/influxdb/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=root_cause_analysis_workflows_influxdb&amp;amp;utm_content=blog"&gt;InfluxDB&lt;/a&gt; shines: you can use queries to stack these metrics on a single time axis.&lt;/p&gt;

&lt;p&gt;Aligning them makes it easy to see, for example, if a spike in traffic caused an increase in saturation or if saturation climbed while traffic stayed completely flat.&lt;/p&gt;

&lt;p&gt;Let’s look at a pair of examples.&lt;/p&gt;

&lt;p&gt;First, let’s use a SQL query to map user impact. It will place average query latency and error count next to each other during the event window.&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT time, 
avg("duration_ms") AS avg_latency, 
count("error_code") AS error_count 
FROM "application_source_events" 
WHERE time BETWEEN '2026-07-05T13:15:00Z' AND '2026-07-05T14:15:00Z' GROUP BY time(1s)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, you can query your concurrency and system metrics over the same window.&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT time, 
count("request_id") AS requests_per_sec, 
avg("cpu_percentage") AS cpu_util, 
avg("pool_active_connections") AS active_db_conns 
FROM "system_telemetry" WHERE time BETWEEN '2026-07-05T13:15:00Z' AND '2026-07-05T14:15:00Z' GROUP BY time(1s)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you stack these queries, you can check for an intersection at &lt;strong&gt;T-0&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Traffic Spike + High Saturation = Capacity Problem&lt;/strong&gt;. Did your systems run out of memory, I/O capacity, or headroom for threads?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flat Traffic + High Saturation = Resource Leak&lt;/strong&gt;. Something, such as a task, an unoptimized query, or a memory leak, is consuming excess resources.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flat Traffic + Low Saturation + High Latency = Blocking&lt;/strong&gt;. This points to an issue that will require more sleuthing. The application is idling, likely because it’s waiting on an external dependency, like a locked database row or an API request that isn’t responding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="drill-down"&gt;Drill Down&lt;/h2&gt;

&lt;p&gt;Those two queries already told us a lot, but InfluxDB is capable of more. You’ve identified which signal caused the issue, but it’s only an average. Now it’s time to find the real culprit.&lt;/p&gt;

&lt;p&gt;InfluxDB’s multi-dimensional tag system tells you where a specific data stream is coming from. And Influx indexes these tags, so you can group, filter, and pivot telemetry to drill down to exactly where your problem started.&lt;/p&gt;

&lt;p&gt;The fastest way to isolate the culprit is to split your failing metric across logical infrastructure boundaries. If your &lt;a href="https://docs.influxdata.com/influxdb/v1/api/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=root_cause_analysis_workflows_influxdb&amp;amp;utm_content=blog"&gt;API&lt;/a&gt; latency spikes, you need to know if the failure is systemic or isolated.&lt;/p&gt;

&lt;p&gt;Here’s a query that groups metrics by container:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT time,
avg("duration_ms") AS metric_value 
FROM "application_source_events" WHERE time BETWEEN '2026-07-05T13:15:00Z' AND '2026-07-05T14:15:00Z' GROUP BY time(10s), "container_id"Identify the "Smoking Gun"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You’ve isolated your timeline, correlated the signals, and used InfluxDB’s tags to isolate the issue. Now for the last step: finding the exact data point that proves causality.&lt;/p&gt;

&lt;p&gt;When you’re waist-high in the proverbial weeds, it’s easy to mistake an outlying metric for the true cause. To prove that event A caused B, your data needs to satisfy these conditions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Precedence&lt;/strong&gt;: The root cause must occur before or exactly at T-0. If it shifted even a few milliseconds later, it’s a symptom.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Proportionality&lt;/strong&gt;: The severity of the outage reacts in proportion to the intensity of	the root cause.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One way to ensure you satisfy these requirements is to look at the delta before the incident occurred. You can do this with an InfluxDB query, too.&lt;/p&gt;

&lt;p&gt;Let’s graph the derivative of active database connections so we can view it alongside the error rate.&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT time, 
derivative("pool_active_connections", 1s) AS connection_change_rate 
FROM "system_telemetry" WHERE time BETWEEN '2026-07-05T13:45:00Z' AND '2026-07-05T14:15:00Z' GROUP BY time(1s)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the rate of new connections accelerated sharply before T-0 and stayed high until and through T-0, you have your smoking gun.&lt;/p&gt;

&lt;h2 id="moving-from-reactive-to-proactive"&gt;Moving from reactive to proactive&lt;/h2&gt;

&lt;p&gt;Root cause analysis doesn’t have to feel like searching for a needle in a haystack. We’ve covered a four-step process that shows you how, treating time as your primary anchor and leveraging InfluxDB’s sophisticated queries, you can systematically perform root cause analysis.&lt;/p&gt;

&lt;p&gt;Explore how &lt;a href="https://www.influxdata.com/influxdb-signup/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=root_cause_analysis_workflows_influxdb&amp;amp;utm_content=blog"&gt;InfluxDB&lt;/a&gt; helps teams collect, analyze, and correlate time series data to accelerate root cause analysis across infrastructure, applications, industrial systems, and IoT environments.&lt;/p&gt;

&lt;h2 id="faqs"&gt;FAQS:&lt;/h2&gt;

&lt;div id="accordion_second"&gt;
    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-1"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How do I choose between using InfluxDB metrics and application logs during an active incident?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-1" class="message-body is-collapsible is-active" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Use InfluxDB to pinpoint your T-0, establish a timeline, and narrow down where the trouble is beginning. Use your application logs to troubleshoot individual components once you’ve identified them as the root cause.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-2"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;What is the impact of querying high-resolution data during a major production outage?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-2" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
               Because InfluxDB is optimized for time series data and its native tags, it’s incredibly fast and lightweight. To minimize database load during production hours, be sure to use a strict time boundary in your queries.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-3"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;3. How do I differentiate between a symptom and the actual root cause if multiple metrics spike at T-0?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-3" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Use InfluxDB’s math functions as a mechanism for an empirical test. You can calculate the rate of change using the derivative() function for the competing metrics. Your root cause will show a sharp increase before the incident, while the symptoms will follow. 
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

&lt;/div&gt;
</description>
      <pubDate>Wed, 14 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/root-cause-analysis-workflows-influxdb/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/root-cause-analysis-workflows-influxdb/</guid>
      <category>Developer</category>
      <author>Community (InfluxData)</author>
    </item>
    <item>
      <title>Why Automotive Manufacturers Are Augmenting Data Historians, Not Replacing Them</title>
      <description>&lt;p&gt;A modern vehicle assembly line generates more time-stamped telemetry before lunch than most data historians were built to hold: weld temperatures, torque readings, and vibration traces from every robot, torque tool, vision system, and test stand, and on most historians, each signal carries its own line-item cost because the systems are still priced per tag. That model was fine when data was scarce; it breaks down as OEMs and Tier 1 and Tier 2 suppliers add sensors, stations, and higher sampling rates every year, turning instrumentation into a budgeting exercise before it becomes a visibility gain.&lt;/p&gt;

&lt;p&gt;The instinct is to rip out the historian and start over. On a validated, IATF 16949-certified production line, that’s rarely realistic: historians from vendors like OSI PI/AVEVA, Wonderware, GE, and Honeywell are wired into SCADA systems, PLCs, robot controllers, and distributed control systems that keep the line running, and replacing that layer risks a stoppage that cascades into missed takt, JIT penalties, and downstream OEM shutdowns within hours. InfluxDB, a purpose-built time series platform, takes a more pragmatic path: augmenting the historian instead of replacing it.&lt;/p&gt;

&lt;h2 id="why-data-historians-are-hitting-a-wall-in-industry-40"&gt;Why data historians are hitting a wall in Industry 4.0&lt;/h2&gt;

&lt;p&gt;Data historians were built for Industry 3.0: one plant, one shift pattern, one set of tags, running on-premises with modest data volumes. They’re still good at that job. What they weren’t built for is Industry 4.0, where interconnected devices, IIoT sensors, and cloud-native systems generate volume, variety, and velocity of telemetry that legacy architectures never had to handle.&lt;/p&gt;

&lt;p&gt;Three problems show up consistently as manufacturers try to close that gap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vendor lock-in&lt;/strong&gt;. Historians are proprietary and tightly controlled by their vendors. Licensing, upgrades, and even adding a tag for a new robot sensor or launch program often require vendor involvement, which locks plants into a single roadmap at a time when margins are already under tariff and EV-transition pressure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability and cost&lt;/strong&gt;. Historians can often handle a surprising volume of tags within a single plant. The real limit is cost, not raw capacity. Adding hundreds of robots, weld guns, and sensors across a modern line means more hardware and more per-tag licensing, and that compounds further at multi-plant scale, where consolidating data across sites becomes both harder and more expensive than adding capacity within one plant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-time limitations&lt;/strong&gt;. Legacy historians weren’t designed for predictive models or AI/ML workloads on high-frequency signals like torque, weld current, or robot vibration. Pulling that data out usually means batch exports or custom connectors, which delay insight and lead to avoidable downtime. In an assembly environment running on takt time measured in seconds, even a small lag can mean a missed beat, stalled production, or overtime.&lt;/p&gt;

&lt;h2 id="ingest-cardinality-and-query-range-at-industry-40-scale"&gt;Ingest, cardinality, and query range at Industry 4.0 scale&lt;/h2&gt;

&lt;p&gt;At Industry 4.0 data volumes, three things decide whether a platform can keep up: how much it can ingest without slowing down, how much metadata per time series is collected, and how far back it can query without switching to a separate system. A time series platform built specifically for this workload, like InfluxDB, is engineered to process millions of data points per second from diverse sources without performance degradation, using indexing that holds up as cardinality grows into the millions.&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Characteristic&lt;/th&gt;
    &lt;th&gt;Data historian&lt;/th&gt;
    &lt;th&gt;Time series platform&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;Ingest volume&lt;/td&gt;
    &lt;td&gt;Thousands of points/second from fixed sources; can be overwhelmed by modern telemetry&lt;/td&gt;
    &lt;td&gt;Millions of data points per second from diverse sources, no performance degradation&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Cardinality&lt;/td&gt;
    &lt;td&gt;Performance degrades as unique tags grow&lt;/td&gt;
    &lt;td&gt;Advanced indexing built for millions of unique time series&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Query range&lt;/td&gt;
    &lt;td&gt;Fast on recent data; long-term history is slow or needs a separate system&lt;/td&gt;
    &lt;td&gt;Real-time and historical data unified for queries across any time range&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Interoperability&lt;/td&gt;
    &lt;td&gt;Proprietary, closed; requires custom connectors&lt;/td&gt;
    &lt;td&gt;Open standards and APIs (SQL, REST, Python, Grafana, Power BI)&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Cost model&lt;/td&gt;
    &lt;td&gt;Per-tag licensing&lt;/td&gt;
    &lt;td&gt;Compute-based, no per-tag penalty&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Interoperability matters just as much as raw throughput: a platform that plugs directly into the tools industrial teams already use, like &lt;a href="https://www.influxdata.com/blog/getting-started-influxdb-3-grafana/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=why_auto_manufacturers_augment_historians&amp;amp;utm_content=blog"&gt;Grafana&lt;/a&gt;, Power BI, Python, and AI/ML pipelines, avoids the expensive custom connectors historians are known for. InfluxDB is built on open standards and APIs for exactly that reason.&lt;/p&gt;

&lt;h2 id="how-influxdb-augments-a-data-historian"&gt;How InfluxDB augments a data historian&lt;/h2&gt;

&lt;p&gt;InfluxDB’s role isn’t to take over what the historian already does well. It’s to take on what the historian was never designed to handle, while the historian keeps running SCADA historization, GxP and regulatory data, and the operator dashboards teams already trust.&lt;/p&gt;

&lt;p&gt;There are two common ways manufacturers deploy InfluxDB alongside a historian.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parallel feed&lt;/strong&gt;. New instrumentation, robots, stations, and  launch programs get routed to InfluxDB instead of adding to the historian’s tag count. &lt;a href="https://www.influxdata.com/time-series-platform/telegraf/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=why_auto_manufacturers_augment_historians&amp;amp;utm_content=blog"&gt;Telegraf&lt;/a&gt;, InfluxData’s open source data collection agent with plugins for OPC-UA, MQTT, and Modbus (the same protocols already used to talk to robot controllers and weld cells), streams that data into InfluxDB with little to no latency. The historian stays in the system of record; InfluxDB handles the dashboards, anomaly detection on weld and torque signatures, and predictive maintenance work that would otherwise wait on the historian’s licensing terms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consolidation&lt;/strong&gt;. Many OEMs and Tier 1 suppliers run several historians, sometimes one per plant, sometimes one per acquired site, that weren’t built to talk to each other. InfluxDB sits downstream of those systems as a central operational layer, unifying siloed feeds into a single source of truth that Grafana or a similar visualization tool can present as one dashboard, shortening launch reviews, quality audits, and warranty investigations that currently require reconciling conflicting data across plants.&lt;/p&gt;

&lt;p&gt;For plants running a wider mix of PLCs, CNCs, and proprietary equipment than Telegraf’s protocol 
plugins cover on their own, InfluxData &lt;a href="https://www.influxdata.com/partners/litmus/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=why_auto_manufacturers_augment_historians&amp;amp;utm_content=blog"&gt;partners with Litmus&lt;/a&gt;, an industrial data operations platform with 250+ prebuilt connectors for OT systems like PLCs, SCADA, and CNC machines. Litmus normalizes and contextualizes raw machine signals at the edge, tagging them with asset, facility, and production-line metadata, while InfluxDB handles ingestion, real-time analysis, and long-term storage of that contextualized telemetry, locally at the plant and replicated to a central hub for fleet-wide visibility.&lt;/p&gt;

&lt;h2 id="automotive-and-industrial-manufacturers-already-running-influxdb"&gt;Automotive and industrial manufacturers already running InfluxDB&lt;/h2&gt;

&lt;p&gt;A few companies already running InfluxDB at automotive scale show what historian augmentation delivers in practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Toyo Tires&lt;/strong&gt; replaced a manual system for quality control and anomaly detection that couldn’t reliably catch defective tires before they left the line, or support the 20-year data retention its audit requirements demand. With InfluxDB Enterprise, Toyo now runs real-time and long-term analysis for quality issues cost-effectively, and has scaled from a single plant in Serbia monitoring 100 machines to as many as 1,000 machines across multiple locations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;American Axle &amp;amp; Manufacturing&lt;/strong&gt;, a Tier 1 automotive and mobility supplier with nearly 85 facilities in 18 countries, runs the &lt;a href="https://www.influxdata.com/blog/infrastructure-monitoring-basics-telegraf-influxdb-grafana/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=why_auto_manufacturers_augment_historians&amp;amp;utm_content=blog"&gt;TIG stack&lt;/a&gt; (Telegraf, InfluxDB, and Grafana) across its enterprise data infrastructure, including monitoring 78 file servers at remote manufacturing sites and database performance alerting. “The combination of Grafana, InfluxDB, and Telegraf is a winning one,” said Stewart McKenna, Systems Administrator at AAM. “It’s really easy to come up with use cases, and the ease of displaying the data to leadership is wonderful.”&lt;/p&gt;

&lt;p&gt;Getting started doesn’t require a disruptive overhaul: route new telemetry, one line, one plant, or one launch program at a time to InfluxDB instead of the historian’s tag count, and expand once that pilot proves the case. InfluxData’s full guide, &lt;em&gt;&lt;a href="https://www.influxdata.com/resources/scaling-time-series-for-automotive-manufacturing/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=why_auto_manufacturers_augment_historians&amp;amp;utm_content=blog"&gt;Scaling Time Series for Automotive Manufacturing&lt;/a&gt;&lt;/em&gt;, covers deployment architectures and a step-by-step path for scaling across a plant network. Manufacturers ready to test it against their own telemetry can &lt;a href="https://www.influxdata.com/proof-of-concept/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=why_auto_manufacturers_augment_historians&amp;amp;utm_content=blog"&gt;request a proof of concept&lt;/a&gt; with InfluxData.&lt;/p&gt;

&lt;h2 id="frequently-asked-questions"&gt;Frequently asked questions&lt;/h2&gt;

&lt;div id="accordion_second"&gt;
    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-1"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How is InfluxDB different from a data historian?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-1" class="message-body is-collapsible is-active" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                InfluxDB is engineered to ingest millions of data points per second from diverse sources, support unlimited cardinality as sensor counts grow, and unify real-time and historical queries in one system. Data historians are typically limited to thousands of points per second from fixed sources, are priced per tag, and often require a separate system for long-term historical analysis.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-2"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;Does augmenting a historian with InfluxDB put IATF 16949 or GxP validation at risk?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-2" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
            No. In an augmentation deployment, InfluxDB sits downstream of the historian and picks up new telemetry, like added sensors, robots, or launch-program data, without disrupting the existing workflows. The validated historian, SCADA, and control systems that keep the line running continue operating exactly as they are, and GxP and other regulatory data stay on the historian, so certification and compliance workflows aren't touched.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-3"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How does data get from plant floor equipment into InfluxDB?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-3" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
              Telegraf, InfluxData's open source data collection agent, connects to plant-floor protocols like OPC-UA, MQTT, and Modbus (the same protocols used by robot controllers and weld cells) and streams that telemetry into InfluxDB with little to no latency. For plants running a wider mix of PLCs, CNCs, and proprietary OT systems, Litmus extends that coverage with 250+ prebuilt connectors, normalizing and contextualizing machine signals at the edge before InfluxDB ingests them.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-4"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How does data get from plant floor equipment into InfluxDB?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-4" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Telegraf, InfluxData's open source data collection agent, connects to plant-floor protocols like OPC-UA, MQTT, and Modbus (the same protocols used by robot controllers and weld cells) and streams that telemetry into InfluxDB with little to no latency. For plants running a wider mix of PLCs, CNCs, and proprietary OT systems, Litmus extends that coverage with 250+ prebuilt connectors, normalizing and contextualizing machine signals at the edge before InfluxDB ingests them.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-5"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;Does getting started require migrating existing historical data out of the historian?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-5" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                No. Augmentation is forward-looking: new telemetry, from added sensors, robots, or a launch program, gets routed to InfluxDB going forward, while the historian keeps its existing history and continues serving lookups against older data. There's no migration project required to start, which is what makes a single-line pilot realistic before committing to a wider rollout.

            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

&lt;/div&gt;
</description>
      <pubDate>Mon, 05 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/why-auto-manufacturers-augment-historians/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/why-auto-manufacturers-augment-historians/</guid>
      <category>Developer</category>
      <category>Use Cases</category>
      <author>Ryan Nelson (InfluxData)</author>
    </item>
    <item>
      <title>What’s New in InfluxDB 3.12: Distributed Compaction, 3x Faster Imports, and More Control </title>
      <description>&lt;p&gt;Time series deployments rarely grow the way they were planned. A single-node pilot becomes a multi-node fleet, an afternoon’s worth of test data becomes weeks of backfill that has to land before anyone can query it, and three teams end up writing to a database built for one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.influxdata.com/blog/influxdb-3-11/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=whats-new-influxdb-3-1-2&amp;amp;utm_content=blog"&gt;InfluxDB 3.11&lt;/a&gt; delivered a higher-performance foundation for complex time series workloads, with significant performance improvements for single-series queries, schemas that could go wide and sparse without breaking, and a much more predictable resource profile.&lt;/p&gt;

&lt;p&gt;For InfluxDB 3 Enterprise, 3.12 builds on that foundation with more ways to scale operations around those workloads. Bulk imports make better use of available CPU, compaction can now scale across nodes, and schema enforcement gives teams more control over shared production datasets.&lt;/p&gt;

&lt;p&gt;The common thread is simple: as the workload grows, more of the system can grow with it.&lt;/p&gt;

&lt;h2 id="bulk-import-now-3x-faster"&gt;Bulk import, now 3x faster&lt;/h2&gt;

&lt;p&gt;Historical data isn’t useful until it’s queryable. When you’re migrating to InfluxDB or backfilling months of history, import speed decides how soon that data sits alongside your live data, whether that’s by lunch or next week.&lt;/p&gt;

&lt;p&gt;InfluxDB 3.12 makes bulk import from Parquet roughly three times faster. Imports now run in parallel, so they scale with the hardware you give them. In testing, import time fell by 64-70 percent across workloads.&lt;/p&gt;

&lt;p&gt;Imports are also easier to lock down. Bulk import no longer requires an admin token. It now authorizes against write permission on the target database, so the credential running a backfill only needs access to the data it’s loading.&lt;/p&gt;

&lt;h2 id="distributed-compaction-now-in-beta"&gt;Distributed compaction, now in beta&lt;/h2&gt;

&lt;p&gt;Compaction keeps queries fast by organizing newly written data into efficient files in the background. At high ingest volumes, though, that background work can become the bottleneck: compaction falls behind, and the only fix is a bigger machine.&lt;/p&gt;

&lt;p&gt;InfluxDB 3.12 removes that ceiling. With distributed compaction, now in beta, compaction becomes something you can scale horizontally. When compaction needs more capacity, add nodes running in compact mode, and the coordinating node spreads jobs across them. If a compact node drops out mid-job, the work is simply reassigned in the next scheduling cycle.&lt;/p&gt;

&lt;p&gt;Distributed compaction is off by default, so existing deployments behave exactly as they do today. When you’re ready to scale past a single compactor, you can turn it on.&lt;/p&gt;

&lt;h2 id="schema-enforcement-per-database"&gt;Schema enforcement, per database&lt;/h2&gt;

&lt;p&gt;Schema-on-write is one of the things that makes InfluxDB easy to start with: send data, and the schema takes shape around it. But in a production database shared by several applications, that flexibility cuts both ways. A typo in a field name or an unexpected column from one service quietly becomes part of the schema, and every team querying that database has to work around it.&lt;/p&gt;

&lt;p&gt;InfluxDB 3.12 lets you lock the schema down where it matters. Define the schema when you create a database, and writes that introduce undefined columns are rejected instead of changing the schema. Bad data gets caught at write time, before it reaches dashboards, queries, or downstream consumers.&lt;/p&gt;

&lt;p&gt;Schema-on-write remains the default, so you can enforce schemas on the databases that production depends on and keep exploratory databases as flexible as ever.&lt;/p&gt;

&lt;h2 id="more-control-in-the-explorer-ui"&gt;More control in the Explorer UI&lt;/h2&gt;

&lt;p&gt;The Explorer UI has a set of updates to keep pace with the teams using it.&lt;/p&gt;

&lt;p&gt;InfluxDB 3.12 makes role-based access control generally available in InfluxDB 3 Enterprise, so teams can manage access by user and role instead of tracking individual tokens. Users can sign in with a token, a password, or SSO, and using Explorer, admins can manage users and their roles from the same place they query.&lt;/p&gt;

&lt;p&gt;Explorer also adds six visualization types: area, single stat, gauge, pie, scatter, and ranking. Explain in SQL shows what a query is doing, which makes it easier to check before you rely on it. New deployments also start with Explorer preconfigured, so the first query doesn’t wait on connection parameters.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/563tWp0YToOwGOolFo1oBW/c9a175c145fb9f7e3cc3aa9316c53996/f4564dd9-02ba-48bd-a90d-d3881808b87e.png" alt="InfluxDB 3.12 " /&gt;&lt;/p&gt;

&lt;h2 id="other-improvements-in-influxdb-3-enterprise"&gt;Other improvements in InfluxDB 3 Enterprise&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The Processing Engine can now run as a separate process&lt;/strong&gt;, so teams can deploy custom Python plugins without worrying about them affecting database stability.&lt;/li&gt;
  &lt;li&gt;InfluxDB 3 Core and Enterprise now run on &lt;strong&gt;Apache DataFusion 52&lt;/strong&gt;, picking up another round of query performance improvements across joins, CASE expressions, and query planning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="upgrading-a-multi-node-deployment"&gt;Upgrading a multi-node deployment?&lt;/h2&gt;

&lt;p&gt;InfluxDB 3.12 has new requirements for node roles and upgrade order. Review the &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/release-notes/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=whats-new-influxdb-3-1-2&amp;amp;utm_content=blog"&gt;release notes&lt;/a&gt; before upgrading.&lt;/p&gt;

&lt;h2 id="get-started-with-influxdb-312"&gt;Get started with InfluxDB 3.12&lt;/h2&gt;

&lt;p&gt;With 3.12, more of InfluxDB scales with your workloads. Compaction can scale horizontally, imports get faster as you add cores, and production schemas no longer have to evolve by accident.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.influxdata.com/downloads/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=whats-new-influxdb-3-1-2&amp;amp;utm_content=blog"&gt;Download the latest version&lt;/a&gt; of InfluxDB 3 Enterprise, pull the newest Docker image, or check out the docs (&lt;a href="https://docs.influxdata.com/influxdb3/core/release-notes/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=whats-new-influxdb-3-1-2&amp;amp;utm_content=blog"&gt;Core&lt;/a&gt;, &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/release-notes/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=whats-new-influxdb-3-1-2&amp;amp;utm_content=blog"&gt;Enterprise&lt;/a&gt;) to get started.&lt;/p&gt;
</description>
      <pubDate>Thu, 01 Oct 2026 08:20:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/influxdb-3-12/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/influxdb-3-12/</guid>
      <category>Product</category>
      <category>Developer</category>
      <category>news</category>
      <author>Peter Barnett (InfluxData)</author>
    </item>
    <item>
      <title>Telegraf 1.40 Release Notes</title>
      <description>
&lt;p&gt;You can find the binaries for the latest Telegraf release on our &lt;a href="https://influxdata.com/downloads"&gt;Downloads page&lt;/a&gt;. Many thanks to all the open source community members who contributed to this effort!&lt;/p&gt;

&lt;h2 id="new-plugins"&gt;New plugins&lt;/h2&gt;

&lt;p&gt;These are the newest plugins, first available in this version:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Databricks Zerobus output&lt;/strong&gt; (&lt;code class="language-markup"&gt;outputs.zerobus&lt;/code&gt;)
    &lt;ul&gt;
      &lt;li&gt;Streams metrics to a Unity Catalog Delta table using the &lt;a href="https://docs.databricks.com/aws/en/ingestion/zerobus-ingest/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_1_40_release_notes_influxdb&amp;amp;utm_content=blog"&gt;Databricks Zerobus Ingest&lt;/a&gt; service over gRPC to directly commit into Delta&lt;/li&gt;
      &lt;li&gt;Contributed by &lt;a href="https://github.com/zlata-stefanovic-db/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_1_40_release_notes_influxdb&amp;amp;utm_content=blog"&gt;zlata-stefanovic-db&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fritzbox Smarthome input&lt;/strong&gt;  (&lt;code class="language-markup"&gt;inputs.fritzbox_smarthome&lt;/code&gt;)
    &lt;ul&gt;
      &lt;li&gt;Reads metrics such as lamp state, energy consumption, etc., from Smarthome-capable &lt;a href="https://fritz.com/"&gt;FRITZ!&lt;/a&gt; routers using the &lt;a href="https://fritz.com/en/pages/interfaces"&gt;AVM Home Automation&lt;/a&gt; interface.&lt;/li&gt;
      &lt;li&gt;Contributed by &lt;a href="https://portal.influxdata.com/downloads/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_1_40_release_notes_influxdb&amp;amp;utm_content=blog"&gt;hdecarne&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="important-changes"&gt;Important changes&lt;/h2&gt;

&lt;p&gt;Here are some changes to highlight:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Cisco Model-Driven-Telemetry fixes&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Several fixes changed the metric format&lt;/li&gt;
      &lt;li&gt;Configured aliases are now respected for microburst and RIB messages, which might result in changes to the metric name&lt;/li&gt;
      &lt;li&gt;Spurious, invalid metrics with wrong tag-sets were removed or corrected&lt;/li&gt;
      &lt;li&gt;Row numbers are now tagged correctly for table messages&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Smart input fix for power-on-hours&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Power-on-hours are now reported correctly for raw values in &lt;code class="language-markup"&gt;182h+39m+24.879s&lt;/code&gt; format&lt;/li&gt;
      &lt;li&gt;Previously, those values resulted in the field containing the time in seconds&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Removal of deprecated plugins&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class="language-markup"&gt;inputs.aerospike&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class="language-markup"&gt;inputs.sflow&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class="language-markup"&gt;outputs.amon&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Removal of deprecated plugin options&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class="language-markup"&gt;inputs.kafka_consumer&lt;/code&gt; removal of &lt;code class="language-markup"&gt;connection_strategy&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class="language-markup"&gt;inputs.openstack&lt;/code&gt; removal of &lt;code class="language-markup"&gt;server_diagnostics&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class="language-markup"&gt;inputs.procstat&lt;/code&gt; removal of &lt;code class="language-markup"&gt;cmdline_tag&lt;/code&gt;, &lt;code class="language-markup"&gt;pid_tag&lt;/code&gt;, and &lt;code class="language-markup"&gt;supervisor_unit&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class="language-markup"&gt;inputs.tail&lt;/code&gt; removal of &lt;code class="language-markup"&gt;from_beginning&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Use the &lt;code class="language-markup"&gt;telegraf config migrate&lt;/code&gt; command to migrate your configuration&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Elasticsearch query input plugin migration to official library&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Migration to official and maintained libraries&lt;/li&gt;
      &lt;li&gt;Additional support for Elasticsearch v7, v8 and v9&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="downloads"&gt;Downloads&lt;/h2&gt;

&lt;p&gt;Head to our &lt;a href="https://portal.influxdata.com/downloads/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_1_40_release_notes_influxdb&amp;amp;utm_content=blog"&gt;Downloads page&lt;/a&gt; to get the latest Telegraf release. If you have issues or questions, please join our &lt;a href="https://influxdata.com/slack/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_1_40_release_notes_influxdb&amp;amp;utm_content=blog"&gt;InfluxDB Community Slack&lt;/a&gt; or post them in our InfluxDB GitHub Repo or &lt;a href="https://community.influxdata.com/c/influxdb2/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_1_40_release_notes_influxdb&amp;amp;utm_content=blog"&gt;Community Site&lt;/a&gt;, and we will look into them.&lt;/p&gt;

&lt;h2 id="influxdb-university"&gt;InfluxDB University&lt;/h2&gt;

&lt;p&gt;Learn more about collecting data with Telegraf by taking the free InfluxDB University &lt;a href="https://university.influxdata.com/courses/data-collection-with-telegraf-tutorial/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_1_40_release_notes_influxdb&amp;amp;utm_content=blog"&gt;Data Collection with Telegraf course&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="faq"&gt;FAQ&lt;/h2&gt;

&lt;div id="accordion_second"&gt;
    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-1"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;What's new in Telegraf 1.40?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-1" class="message-body is-collapsible is-active" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Telegraf 1.40 adds two new plugins: a Databricks Zerobus output plugin for streaming metrics directly into Unity Catalog Delta tables over gRPC, and a Fritzbox Smarthome input plugin for reading device metrics from AVM's FRITZ! routers. The release also fixes several Cisco Model-Driven-Telemetry issues, corrects a SMART input bug for power-on-hours reporting, and migrates the Elasticsearch query input plugin to an official, maintained library with added support for Elasticsearch v7, v8, and v9.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-2"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;Which Telegraf plugins were removed in 1.40?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-2" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Three deprecated input/output plugins were removed: inputs.aerospike, inputs.sflow, and outputs.amon. If you're running configurations that use any of these, you'll need to migrate to an alternative plugin before upgrading.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-3"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;What deprecated plugin options were removed in Telegraf 1.40?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-3" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Several plugin-specific options were dropped: &lt;code class="language-markup"&gt;connection_strategy&lt;/code&gt; from &lt;code class="language-markup"&gt;inputs.kafka_consumer&lt;/code&gt;, &lt;code class="language-markup"&gt;server_diagnostics from &amp;lt;/code class="language-markup"&amp;gt;inputs.openstack&lt;/code&gt;, and &lt;code class="language-markup"&gt;cmdline_tag&lt;/code&gt;, &lt;code class="language-markup"&gt;pid_tag&lt;/code&gt;, and &lt;code class="language-markup"&gt;supervisor_unit&lt;/code&gt; from &lt;code class="language-markup"&gt;inputs.procstat&lt;/code&gt;. The &lt;code class="language-markup"&gt;from_beginning&lt;/code&gt; option was also removed from &lt;code class="language-markup"&gt;inputs.tail&lt;/code&gt;. InfluxData recommends running &lt;code class="language-markup"&gt;telegraf config migrate&lt;/code&gt; to automatically update existing configuration files affected by these removals.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-4"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How do I download and get support for Telegraf 1.40?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-4" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Binaries are available on InfluxData's Downloads page. For questions or issues, join the InfluxDB Community Slack or post on the InfluxDB Community Site. InfluxData also offers a free "Data Collection with Telegraf" course through InfluxDB University for those new to the tool.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

&lt;/div&gt;
</description>
      <pubDate>Tue, 15 Sep 2026 00:00:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/telegraf-1-40-release-notes-influxdb/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/telegraf-1-40-release-notes-influxdb/</guid>
      <category>Product</category>
      <category>Developer</category>
      <author>Sven Rebhan (InfluxData)</author>
    </item>
    <item>
      <title> Building a Practical Time Series Data Layer for Automotive Manufacturing</title>
      <description>&lt;p&gt;Automotive manufacturing generates data at several operating cadences. Sensors and controllers emit measurements continuously. Equipment and line states change as events. Production and quality systems add context at the part, batch, shift, and plant level. Together, these records describe how a manufacturing process behaves over time.&lt;/p&gt;

&lt;p&gt;That data can support plant visibility, investigations, scrap reduction, condition monitoring, and longer-term comparison, but only if the storage and query layer can keep up with the workload. InfluxDB is a practical fit for these types of workloads because it is optimized for continuous, time-stamped data and can process, retain, and query it without requiring every system around it to be redesigned.&lt;/p&gt;

&lt;h2 id="why-automotive-data-is-a-time-series-workload"&gt;Why automotive data is a time series workload&lt;/h2&gt;

&lt;p&gt;A time series workload is, at its core, any data where you primarily store, query, and analyze it by looking at when it happened and how it progressed from one state to another.&lt;/p&gt;

&lt;p&gt;A temperature measurement in a time series workload never exists in isolation. When a device overheats, you ask how long it took to heat up, whether it had opportunities to cool down, and what that looked like over the span of five, ten, or fifty minutes. The same principles can apply to vibration, torque, current, pressure, flow, cycle state, machine availability, inspection results, alarms, and many  other signals generated during vehicle and component production.&lt;/p&gt;

&lt;p&gt;Queries are written to understand what changed during a particular interval, whether a condition persisted, how one shift compared with another, or how several signals behaved around a production or quality event. Those queries tend to start with a filter on timestamps to the relevant window in which questions are being asked, narrow the data to the relevant equipment or process, and then aggregate, compare, or retrieve the latest values.&lt;/p&gt;

&lt;p&gt;The write pattern of time series data is often distinctive, too. Sensors create readings at a regular cadence, so new data points arrive continuously, almost exclusively as appends to the database, with few or no updates or edits to historical rows.&lt;/p&gt;

&lt;p&gt;The same data also has value at very different time scales. Recent, high-resolution telemetry can support detailed investigations. Longer-range summaries can support plant management, capacity planning, process comparison, forecasting, and cross-plant visibility. Keeping every full-resolution observation may be difficult to justify, but reducing everything to hourly averages at ingestion time throws away information before anyone knows whether it will matter.&lt;/p&gt;

&lt;p&gt;This combination of continuous writes, time-bounded reads, multiple resolutions, and changing retention value is what makes automotive telemetry a time series workload.&lt;/p&gt;

&lt;p&gt;Automotive systems also contain plenty of data that doesn’t fit this description. Bills of material, work orders, user accounts, inventory records, and transactional production data may belong in an MES, ERP system, or relational database. InfluxDB is designed to operationalize telemetry, and it’s part of a well-orchestrated tech stack.&lt;/p&gt;

&lt;h2 id="why-use-a-time-series-database"&gt;Why use a time series database?&lt;/h2&gt;

&lt;p&gt;Any relational database (or even Excel) can store time-stamped measurements. The question is: how efficiently, effectively, and easily can they handle a time series workload, and can they scale? We already have &lt;a href="https://www.influxdata.com/blog/why-time-series-database-influxdb/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=time_series_for_auto_manufacturing&amp;amp;utm_content=blog"&gt;a blog on this topic&lt;/a&gt; that explains the advantages of time series databases, and it’s a good place to start if you want to understand their key advantages.&lt;/p&gt;

&lt;p&gt;To summarize for automotive telemetry: InfluxDB most efficiently handles high-volume ingestion and time-oriented querying, while &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/reference/internals/data-retention/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=time_series_for_auto_manufacturing&amp;amp;utm_content=blog"&gt;database- and table-level retention&lt;/a&gt; lets you control how long each data type remains available. A high-volume raw table can have a shorter retention period than a cleaned or downsampled table in the same database, and because InfluxDB 3 is designed and built for low-cost object storage, data costs stay low. Even better, all tables are very efficiently compressed, minimizing the footprint in object storage and lowering costs.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/admin/last-value-cache/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=time_series_for_auto_manufacturing&amp;amp;utm_content=blog"&gt;Last Value Cache&lt;/a&gt; addresses another common query pattern: retrieving the newest value, or last few values, for each series. That is useful for current-state views where repeatedly scanning recent history would be unnecessary work.&lt;/p&gt;

&lt;p&gt;These features map directly to the shape of automotive manufacturing data workloads, which ingest continuously, query by time, keep recent detail, summarize older data, and serve current state efficiently. This makes a time-series database like InfluxDB the only cost-effective, performant, scalable choice for high-volume, time series workloads.&lt;/p&gt;

&lt;h2 id="a-reference-architecture-for-automotive-manufacturing"&gt;A reference architecture for automotive manufacturing&lt;/h2&gt;

&lt;p&gt;Rather than talking about it at a high level, it may be easier to show you how the architecture works in action.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/influxdata/influxdb3-ref-auto-manufacturing?utm_source=chatgpt.com/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=time_series_for_auto_manufacturing&amp;amp;utm_content=blog"&gt;InfluxDB 3 automotive manufacturing reference architecture&lt;/a&gt; is a runnable example of an automotive time series pipeline. It uses Docker Compose, InfluxDB 3 Enterprise, Processing Engine plugins, and a small web UI:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;git clone https://github.com/influxdata/influxdb3-ref-auto-manufacturing.git
cd influxdb3-ref-auto-manufacturing
make up&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On first boot, the setup asks for an email address and sends an InfluxDB 3 Enterprise license-validation link. After validation, this stack begins generating and processing the simulated plant data, and you can see it by opening the UI at:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;http://localhost:8080&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The repository installs InfluxDB-approved plugins, creates tables and triggers, runs the processing chain, and exposes raw, processed, downsampled, and forecast data through the UI. It also demonstrates isolated station pipelines and a Last Value Cache for current-state views.&lt;/p&gt;

&lt;p&gt;Make sure you read the production notes before using it as a deployment template. The demo is single-node, uses a file-backed object store, shares an admin token between services, and does not enable TLS inside the Compose network. Production requires scoped service tokens, TLS, durable object storage, monitoring, backup planning, and an appropriate multi-node topology. One easy-to-miss detail: create source tables before registering WAL triggers, or the triggers may never fire.&lt;/p&gt;

&lt;p&gt;The repository’s most useful pattern is its separation of concerns. You can replace the signal generator with an OPC UA, historian, or gateway feed and keep the downstream stages. You can change the filter without rewriting the dashboard, or you can change retention without touching the PLC.&lt;/p&gt;

&lt;h2 id="building-on-the-reference-architecture"&gt;Building on the reference architecture&lt;/h2&gt;

&lt;p&gt;Obviously, this is a reference architecture, and it’s meant to be the first step towards building the architecture for your deployment. The most obvious first change to make is replacing the signal generator with an actual data source.&lt;/p&gt;

&lt;p&gt;The repository is deliberately structured so that this happens at the input boundary. &lt;a href="https://docs.influxdata.com/telegraf/v1/input-plugins/opcua/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=time_series_for_auto_manufacturing&amp;amp;utm_content=blog"&gt;Telegraf’s OPC UA input&lt;/a&gt; can collect data from an OPC UA server and write it to InfluxDB. An industrial integration platform such as Litmus or HighByte can write line protocol through the InfluxDB write API. A historian or existing plant application can also become the source if it already exposes the required data. Downstream processing stages don’t need to know which route the points took to get there.&lt;/p&gt;

&lt;p&gt;From there, the work becomes signal-specific.&lt;/p&gt;

&lt;p&gt;A regular time grid may be necessary when several sensors need to be aligned or when an algorithm expects a stable sample rate. It may add little value for an event stream. Gap filling should be bounded and explicit, and ideally preserve enough metadata to distinguish observed values from generated ones. Some gaps should remain gaps because the absence of data is useful information, as it can indicate that certain systems were paused or sensors stopped generating readings.&lt;/p&gt;

&lt;p&gt;Filtering requires similar care. A filter that cleans up a slowly changing booth-temperature signal may be inappropriate for current, vibration, pressure, or torque. Before filtering a production stream, test the filter against the events engineers actually need to preserve. Keep the raw signal long enough to compare the processed output against it.&lt;/p&gt;

&lt;p&gt;Downsampling is another place to be deliberate. Whether you use an average, minimum, maximum, or median, downsampling necessarily entails losing some information. Fortunately, the &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/plugins/library/official/downsampler/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=time_series_for_auto_manufacturing&amp;amp;utm_content=blog"&gt;Downsampler plugin&lt;/a&gt; can generate several calculations for the same source measurement. Useful output might include an average for long-term trends, a maximum for threshold analysis, and a count to show whether the interval contained the expected number of observations.&lt;/p&gt;

&lt;p&gt;Retention follows the same logic. Raw telemetry can remain available for the period in which detailed investigations are likely. Intermediate processing tables may only need to exist long enough to support the next stage. Cleaned or downsampled data can remain available for longer-range analysis. InfluxDB’s table-level retention overrides make it possible to apply those policies within the same database, so that data can flow from maximal-resolution fresh tables into lower-resolution longer-term storage. This ensures all data is available when needed, without paying to store immense volumes of data that will only be used for sporadic historical analysis.&lt;/p&gt;

&lt;p&gt;Finally, the local deployment needs ordinary production hardening. The repository’s architecture notes cover moving from local files to S3, Google Cloud Storage, or Azure Blob Storage; separating ingest, query, compaction, and processing roles; using scoped tokens for individual services; and enabling TLS across trust boundaries. Plugins should also have version control, automated tests, resource limits, and a repeatable deployment process. Running Python inside the database removes some infrastructure, but it’s still production code.&lt;/p&gt;

&lt;h2 id="augmenting-an-existing-automotive-data-stack"&gt;Augmenting an existing automotive data stack&lt;/h2&gt;

&lt;p&gt;Many automotive environments already have control systems, historians, manufacturing applications, quality systems, and enterprise analytics infrastructure. There’s no need to displace them before evaluating InfluxDB. Similarly, the justification for adding InfluxDB doesn’t depend on proving that the historian, warehouse, or relational database is bad. It depends on whether a specialized time series database can serve a particular workload more efficiently.&lt;/p&gt;

&lt;p&gt;A useful entry point is to start bounded, picking a specific task or domain where InfluxDB may be worth leveraging. Mirror data from that domain into InfluxDB, but allow your existing systems to remain authoritative. Because InfluxDB 3 uses SQL, you can likely run the same queries across your existing system and InfluxDB at the same time, and just like that, you’re testing which system is more efficient. How fresh is the data? What’s the query latency, especially when you’re leveraging the Last Value Cache?&lt;/p&gt;

&lt;p&gt;Once it’s running, you can see what else InfluxDB unlocks for you. Use the Processing Engine with ML plugins to detect anomalies and generate forecasts that help with predictive maintenance. Hook into the InfluxDB MCP server to power your AI agents with your data. The database is the backbone, and what you build on top of it is where you truly begin to derive value.&lt;/p&gt;

&lt;p&gt;Measure sustained ingestion, storage consumption at each resolution, query latency for real investigation patterns, and operational overhead. Ask yourself how useful the resulting analysis, forecasts, and downstream tools you built are. A bounded evaluation with representative data gives you evidence from your own workload, which is what truly matters for your use case.&lt;/p&gt;

&lt;h2 id="bringing-it-all-together"&gt;Bringing it all together&lt;/h2&gt;

&lt;p&gt;Automotive telemetry has the defining characteristics of a time series workload: continuous writes, time-bounded queries, value at multiple resolutions, and a useful lifetime that changes as the data ages.&lt;/p&gt;

&lt;p&gt;InfluxDB provides a specialized solution for that workload. The automotive reference architecture makes the design concrete by showing how ingestion, resampling, gap filling, filtering, downsampling, forecasting, caching, and retention can fit together without becoming one inseparable pipeline. Once you’ve got the data flowing, you’ll unlock new capabilities to maximize the value you get from your data, driving efficiency and better data-driven results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.influxdata.com/products/influxdb3-enterprise/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=time_series_for_auto_manufacturing&amp;amp;utm_content=blog"&gt;Get started with a free trial of InfluxDB 3 Enterprise, and try it out today.
&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Wed, 09 Sep 2026 08:00:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/time-series-for-auto-manufacturing/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/time-series-for-auto-manufacturing/</guid>
      <category>Developer</category>
      <author>Cole Bowden (InfluxData)</author>
    </item>
    <item>
      <title>Getting Started with InfluxDB 3 and Grafana Tutorial </title>
      <description>&lt;p&gt;InfluxDB and Grafana are the most common pairing in time series monitoring, and division of labor between them is simple. InfluxDB stores and queries the data: high-volume, time-stamped readings from sensors, servers, meters, vehicles, and anything else that emits time series. Grafana visualizes the data: dashboards, time series panels, stat tiles, state timelines, and alerts. 
Neither tool replaces the other, and many production monitoring stacks run both.&lt;/p&gt;

&lt;p&gt;Connecting them has gotten considerably simpler with InfluxDB 3. Grafana ships with a built-in InfluxDB datasource that speaks InfluxDB 3 SQL over Flight SQL, so there is no third-party plugin to install and no custom query language to learn.&lt;/p&gt;

&lt;p&gt;This guide walks through that integration end-to-end using a realistic dataset you generate yourself. You will learn the following in this tutorial:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Getting data in&lt;/strong&gt; - Writing line protocol and what tags, fields, and timestamps mean for how you will query later.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Transforming data as it arrives&lt;/strong&gt; - Using an InfluxDB 3 Python Processing Engine plugin to turn raw readings into a derived table of decisions. This pattern keeps dashboard queries simple and your source data untouched.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Connecting Grafana securely&lt;/strong&gt; - Read-only tokens and the datasource settings that actually matter.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Building a real dashboard&lt;/strong&gt; - Template variables, chained variables, &lt;code class="language-markup"&gt;$__timeFilter&lt;/code&gt;, &lt;code class="language-markup"&gt;date_bin()&lt;/code&gt; for downsampling, and eight panels across stats, time series, state timelines, bar gauges, and tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="what-you-will-build-with-influxdb-3-and-grafana"&gt;What you will build with InfluxDB 3 and Grafana&lt;/h2&gt;

&lt;p&gt;To make all of that concrete, you will generate a week of smart-building data. The generator is deterministic, so your numbers will match the expected output at every step, and you can verify each stage rather than guessing.&lt;/p&gt;

&lt;p&gt;The raw table, &lt;code class="language-markup"&gt;building_telemetry&lt;/code&gt;, preserves the original readings. The derived table, &lt;code class="language-markup"&gt;iaq_assessment&lt;/code&gt;, adds an indoor-air-quality risk score, a severity label, a recommended action, and a conservative estimate of energy used above an idle baseline. The finished dashboard answers four questions an operator actually asks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Which occupied rooms experienced unhealthy air?&lt;/li&gt;
  &lt;li&gt;Where did CO₂ and PM2.5 spike?&lt;/li&gt;
  &lt;li&gt;How much energy was consumed while rooms were empty?&lt;/li&gt;
  &lt;li&gt;Which building zones should someone investigate first?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dataset has four incidents deliberately built into it. A stuffy Tuesday conference room, a lab drawing power on an empty Wednesday evening, a Thursday ventilation problem in the design studio, and a building-wide Friday particulate event, so every panel has something real to show.&lt;/p&gt;

&lt;p&gt;Buildings are just an example. The architecture in this tutorial applies unchanged to industrial equipment, fleet telemetry, energy metering, network devices, or application metrics. If you are evaluating InfluxDB and Grafana for any of those, this is a working template.&lt;/p&gt;

&lt;h4 id="prerequisites"&gt;Prerequisites&lt;/h4&gt;

&lt;p&gt;This walk-through assumes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A Debian- or Ubuntu-based Linux environment; Grafana also publishes installation instructions for &lt;a href="https://grafana.com/docs/grafana/latest/setup-grafana/installation/redhat-rhel-fedora/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;RHEL, Fedora&lt;/a&gt;, and other supported systems.&lt;/li&gt;
  &lt;li&gt;Python 3.9 (or newer).&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;sudo&lt;/code&gt; access for installing Grafana.&lt;/li&gt;
  &lt;li&gt;An InfluxDB 3 Enterprise trial, at-home, or commercial license.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="why-use-grafanas-built-in-influxdb-datasource"&gt;Why use Grafana’s built-in InfluxDB datasource?&lt;/h2&gt;

&lt;p&gt;Grafana includes an InfluxDB datasource that supports InfluxDB 3 SQL out of the box. There’s no need to install anything else, which makes getting started easy.&lt;/p&gt;

&lt;p&gt;Other choices still have valid uses:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;InfluxQL is supported by the plugin as well, and is useful when migrating existing InfluxDB 1.x queries or working through an HTTP/1.1-only proxy.&lt;/li&gt;
  &lt;li&gt;A separately hosted Grafana is useful for a shared observability platform, but its backend needs private, HTTP/2-capable access to the InfluxDB query node.&lt;/li&gt;
  &lt;li&gt;A custom API can add domain-specific authorization or reshape data, but it adds another service that a beginner tutorial does not need.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id="create-your-project-directory"&gt;Create Your Project Directory&lt;/h4&gt;

&lt;p&gt;Create a folder anywhere convenient and open it in your text editor:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;mkdir smart-building-demo
cd smart-building-demo
mkdir plugins influxdb-data&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The tutorial uses only these local paths:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;smart-building-demo/
├── generate.py
├── smart-building.lp
├── influxdb-data/
└── plugins/
    └── iaq_assessment.py&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Keep the terminal in &lt;code class="language-markup"&gt;smart-building-demo&lt;/code&gt; for the remaining commands.&lt;/p&gt;

&lt;h4 id="install-and-start-influxdb-3-enterprise"&gt;Install and Start InfluxDB 3 Enterprise&lt;/h4&gt;

&lt;p&gt;InfluxData provides a quick installer for Linux and macOS. Download the installer first so you can inspect it before running:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;curl -o /tmp/install_influxdb3.sh \
  https://www.influxdata.com/d/install_influxdb3.sh

# Optional: inspect the downloaded script before running it.
less /tmp/install_influxdb3.sh

sh /tmp/install_influxdb3.sh enterprise&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The installer tracks the latest InfluxDB 3 Enterprise release. For production, InfluxData recommends its DEB/RPM packages or a carefully secured container deployment; see the &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/install/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;official installation guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Verify that the binary is available:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 --version&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the command is not found, open a new terminal or follow the installer’s instructions for adding the binary to your &lt;code class="language-markup"&gt;PATH&lt;/code&gt;, then return to the demo directory.&lt;/p&gt;

&lt;h4 id="start-the-database-with-the-processing-engine-enabled"&gt;Start the Database with the Processing Engine Enabled&lt;/h4&gt;

&lt;p&gt;Run InfluxDB in the first terminal and leave it running:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 serve \
  --node-id smart-building-node \
  --cluster-id smart-building-cluster \
  --object-store file \
  --data-dir "$PWD/influxdb-data" \
  --plugin-dir "$PWD/plugins"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code class="language-markup"&gt;--plugin-dir&lt;/code&gt; flag activates the Processing Engine and tells InfluxDB where to find the Python file you will create. The data directory persists the database between restarts. These options are documented in the &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/plugins/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;Processing Engine guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the first start, InfluxDB asks you to choose and activate a license. A trial provides full Enterprise features for 30 days; the at-home license is intended for eligible hobbyist use. Follow the prompts and email-verification step described in the &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/admin/license/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;license documentation&lt;/a&gt;. Do not include license files, license JWTs, or account details in screenshots or source code.&lt;/p&gt;

&lt;h4 id="create-and-store-the-administrator-token"&gt;Create and Store the Administrator Token&lt;/h4&gt;

&lt;p&gt;Open a second terminal, return to &lt;code class="language-markup"&gt;smart-building-demo&lt;/code&gt;, and create the initial administrator token:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 create token --admin&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;InfluxDB displays this token only once. Store it in a password manager. Then load it into the current terminal without placing it in shell history:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;read -rsp "Paste the InfluxDB administrator token: " INFLUXDB_TOKEN
echo
export INFLUXDB3_AUTH_TOKEN="$INFLUXDB_TOKEN"
export INFLUXDB3_HOST_URL="http://127.0.0.1:8181"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Do not put the token in &lt;code class="language-markup"&gt;generate.py&lt;/code&gt;, the plugin, Grafana queries, screenshots, or a committed shell script. InfluxDB’s &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/get-started/setup/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;authorization setup guide&lt;/a&gt; recommends the &lt;code class="language-markup"&gt;INFLUXDB3_AUTH_TOKEN&lt;/code&gt; environment variable for CLI authentication.&lt;/p&gt;

&lt;p&gt;Create a database for the demo:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;export INFLUXDB_DATABASE="smart_building"
influxdb3 create database "$INFLUXDB_DATABASE"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Expected result: the command completes without an error. You can confirm the database exists with:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 show databases&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id="generate-a-demo-telemetry-data"&gt;Generate a Demo Telemetry Data&lt;/h4&gt;

&lt;p&gt;A good tutorial dataset should be small, understandable, and repeatable. This generator creates six zones, sampled every five minutes for seven days.&lt;/p&gt;

&lt;p&gt;In your editor, create &lt;code class="language-markup"&gt;generate.py&lt;/code&gt; in &lt;code class="language-markup"&gt;smart-building-demo&lt;/code&gt; and paste the following code:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-python"&gt;#!/usr/bin/env python3
"""Generate deterministic smart-building telemetry as InfluxDB line protocol."""

from __future__ import annotations

from datetime import datetime, timedelta, timezone
import math
from pathlib import Path
import random

START = datetime(2026, 8, 10, tzinfo=timezone.utc)
INTERVAL = timedelta(minutes=5)
POINTS_PER_ZONE = 7 * 24 * 12

ZONES = [
    {"building": "hq", "floor": "1", "zone": "open_office", "sensor": "hq-1-open", "capacity": 40, "offset": 0.0},
    {"building": "hq", "floor": "1", "zone": "conference_a", "sensor": "hq-1-conf-a", "capacity": 12, "offset": 0.3},
    {"building": "hq", "floor": "1", "zone": "cafe", "sensor": "hq-1-cafe", "capacity": 50, "offset": 0.7},
    {"building": "hq", "floor": "2", "zone": "lab", "sensor": "hq-2-lab", "capacity": 20, "offset": 0.5},
    {"building": "annex", "floor": "1", "zone": "design_studio", "sensor": "annex-1-design", "capacity": 24, "offset": -0.2},
    {"building": "annex", "floor": "2", "zone": "meeting_room", "sensor": "annex-2-meeting", "capacity": 10, "offset": 0.1},
]

def occupancy_for(zone: dict[str, object], ts: datetime, rng: random.Random) -&amp;gt; int:
    hour = ts.hour + ts.minute / 60
    weekday = ts.weekday() " 5
    capacity = int(zone["capacity"])
    name = str(zone["zone"])

    if not weekday:
        base = 0
    elif 8 "= hour " 18:
        profile = {
            "open_office": 0.64,
            "conference_a": 0.34,
            "cafe": 0.18,
            "lab": 0.48,
            "design_studio": 0.70,
            "meeting_room": 0.28,
        }[name]
        curve = 0.82 + 0.18 * math.sin((hour - 8) * math.pi / 10)
        base = round(capacity * profile * curve)
    else:
        base = 0

    if weekday and name == "cafe" and 11.5 "= hour " 13.5:
        base = round(capacity * 0.88)
    if ts.weekday() == 1 and name == "conference_a" and 14 "= hour " 16:
        base = capacity
    if ts.weekday() == 3 and name == "design_studio" and 9 "= hour " 12:
        base = round(capacity * 0.92)

    return max(0, min(capacity, base + rng.randint(-1, 1)))

def values_for(zone: dict[str, object], ts: datetime, rng: random.Random):
    occupancy = occupancy_for(zone, ts, rng)
    capacity = int(zone["capacity"])
    hour = ts.hour + ts.minute / 60
    zone_name = str(zone["zone"])
    diurnal = math.sin((hour - 7) * math.pi / 12)
    load = occupancy / capacity if capacity else 0

    temperature = 21.3 + float(zone["offset"]) + 1.3 * diurnal + 1.1 * load + rng.uniform(-0.18, 0.18)
    humidity = 43.0 - 4.0 * diurnal + 3.0 * load + rng.uniform(-0.8, 0.8)
    co2 = round(430 + 530 * load + rng.uniform(-18, 18))
    pm25 = 5.2 + 2.8 * load + rng.uniform(-0.7, 0.7)
    power = 0.65 + 0.10 * occupancy + max(0.0, temperature - 23.0) * 0.42 + rng.uniform(-0.12, 0.12)

    # Deterministic incidents used by the dashboard.
    if ts.weekday() == 1 and zone_name == "conference_a" and 14 "= hour " 16:
        co2 += round(720 + 80 * math.sin((hour - 14) * math.pi / 2))
    if ts.weekday() == 3 and zone_name == "design_studio" and 9 "= hour " 12:
        co2 += round(560 + 70 * math.sin((hour - 9) * math.pi / 3))
    if ts.weekday() == 4 and 9 "= hour " 14:
        pm25 += 20 + 4 * math.sin((hour - 9) * math.pi / 5)
    if ts.weekday() == 2 and zone_name == "lab" and 19 "= hour " 22:
        power += 5.5

    return (
        occupancy,
        round(temperature, 2),
        round(humidity, 2),
        int(co2),
        round(pm25, 2),
        round(max(power, 0.1), 2),
    )

def main() -&amp;gt; None:
    output = Path("smart-building.lp")
    rng = random.Random(20260821)
    rows = 0

    with output.open("w", encoding="utf-8") as handle:
        for tick in range(POINTS_PER_ZONE):
            ts = START + tick * INTERVAL
            epoch_s = int(ts.timestamp())

        for zone in ZONES:
                occupancy, temperature, humidity, co2, pm25, power = values_for(zone, ts, rng)
                tags = (
                    f"building={zone['building']},floor={zone['floor']},"
                    f"zone={zone['zone']},sensor_id={zone['sensor']}"
                )
                fields = (
                    f"temperature_c={temperature:.2f},humidity_pct={humidity:.2f},"
                    f"co2_ppm={co2}i,pm25_ug_m3={pm25:.2f},power_kw={power:.2f},"
                    f"occupancy={occupancy}i,capacity={zone['capacity']}i"
                )
                handle.write(f"building_telemetry,{tags} {fields} {epoch_s}\n")
                rows += 1

    print(f"wrote {rows} deterministic rows to {output}")

if __name__ == "__main__":
    main()&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Run the generator:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;python3 generate.py
wc -l smart-building.lp&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Expected output:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;wrote 12096 deterministic rows to smart-building.lp
12096 smart-building.lp&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can open &lt;code class="language-markup"&gt;smart-building.lp&lt;/code&gt; in your editor to inspect the line protocol. Each line contains:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Tags&lt;/strong&gt;: &lt;code class="language-markup"&gt;building&lt;/code&gt;, &lt;code class="language-markup"&gt;floor&lt;/code&gt;, &lt;code class="language-markup"&gt;zone&lt;/code&gt;, and &lt;code class="language-markup"&gt;sensor_id&lt;/code&gt; are low-cardinality dimensions used for filtering and grouping.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fields&lt;/strong&gt;: temperature, humidity, CO₂, PM2.5, power, occupancy, and capacity are values that change over time.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Timestamp&lt;/strong&gt;: epoch seconds—the ingestion command will specify &lt;code class="language-markup"&gt;--precision s&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id="add-an-influxdb-python-processing-engine-plugin"&gt;Add an InfluxDB Python Processing Engine Plugin&lt;/h4&gt;

&lt;p&gt;Raw sensor values are valuable, but operators usually want a smaller set of decisions: Is the room healthy? How urgent is the problem? What should someone check?&lt;/p&gt;

&lt;p&gt;Create &lt;code class="language-markup"&gt;plugins/iaq_assessment.py&lt;/code&gt; in your editor and paste this code:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-python"&gt;"""Create dashboard-ready indoor-air-quality assessments from raw telemetry.

InfluxDB 3 injects LineBuilder and influxdb3_local at runtime.
"""

def _classify(row):
    co2 = int(row["co2_ppm"])
    pm25 = float(row["pm25_ug_m3"])
    temperature = float(row["temperature_c"])
    humidity = float(row["humidity_pct"])
    occupancy = int(row["occupancy"])
    power_kw = float(row["power_kw"])

    co2_component = min(70, max(0, round((co2 - 800) / 8)))
    pm_component = min(30, max(0, round((pm25 - 8) * 2)))
    comfort_component = (
        10
        if temperature " 20
        or temperature &amp;gt; 25
        or humidity " 30
        or humidity &amp;gt; 60
        else 0
    )
    risk_score = min(100, co2_component + pm_component + comfort_component)

    if risk_score &amp;gt;= 70:
        severity = "critical"
    elif risk_score &amp;gt;= 45:
        severity = "high"
    elif risk_score &amp;gt;= 20:
        severity = "moderate"
    else:
        severity = "normal"

    if co2 &amp;gt; 1000 and occupancy &amp;gt; 0:
        recommendation = "increase_ventilation"
    elif pm25 &amp;gt; 25:
        recommendation = "check_filtration"
    elif comfort_component:
        recommendation = "balance_hvac"
    else:
        recommendation = "monitor"

    energy_waste_kw = max(0.0, power_kw - 1.5) if occupancy == 0 else 0.0
    return risk_score, severity, recommendation, energy_waste_kw

def process_writes(influxdb3_local, table_batches, args=None):
    processed = 0

    for table_batch in table_batches:
        if table_batch["table_name"] != "building_telemetry":
            continue

        for row in table_batch["rows"]:
            risk_score, severity, recommendation, energy_waste_kw = _classify(row)
            line = (
                LineBuilder("iaq_assessment")
                .tag("building", row["building"])
                .tag("floor", row["floor"])
                .tag("zone", row["zone"])
                .tag("severity", severity)
                .int64_field("risk_score", risk_score)
                .int64_field(
                    "co2_excess_ppm", max(0, int(row["co2_ppm"]) - 800)
                )
                .string_field("recommendation", recommendation)
                .float64_field("energy_waste_kw", energy_waste_kw)
                .bool_field("occupied", int(row["occupancy"]) &amp;gt; 0)
                .time_ns(int(row["time"]))
            )
            influxdb3_local.write(line)
            processed += 1

    influxdb3_local.info(
        f"iaq_assessment processed {processed} building_telemetry rows"
    )&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The plugin deliberately uses only the API InfluxDB injects and the Python standard library, so you don’t have to install any packages.&lt;/p&gt;

&lt;h4 id="understanding-the-risk-calculation"&gt;Understanding the Risk Calculation&lt;/h4&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;CO₂ component     = clamp(round((co2_ppm - 800) / 8), 0, 70)
PM2.5 component   = clamp(round((pm25_ug_m3 - 8) × 2), 0, 30)
comfort component = 10 outside 20–25 °C or 30–60% humidity
risk score        = min(100, all three components added together)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The score becomes one of four states:&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Score&lt;/th&gt;
    &lt;th&gt;Severity&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;0–19&lt;/td&gt;
    &lt;td&gt;normal&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;20–44&lt;/td&gt;
    &lt;td&gt;moderate&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;45–69&lt;/td&gt;
    &lt;td&gt;high&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;70–100&lt;/td&gt;
    &lt;td&gt;critical&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;The rules are intentionally simple and transparent. They are tutorial logic, not a health, safety, or regulatory standard.&lt;/p&gt;

&lt;p&gt;The plugin also calculates &lt;code class="language-markup"&gt;energy_waste_kw&lt;/code&gt;. When occupancy is zero, it counts only power above a conservative 1.5 kW idle baseline. This is different from counting all energy used while a room is empty, which is shown in the dashboards.&lt;/p&gt;

&lt;h4 id="raw-and-derived-table-schemas"&gt;Raw and derived table schemas&lt;/h4&gt;

&lt;p&gt;The first write creates the raw &lt;code class="language-markup"&gt;building_telemetry&lt;/code&gt; table:&lt;/p&gt;

&lt;p&gt;The plugin creates &lt;code class="language-markup"&gt;iaq_assessment&lt;/code&gt;:&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Columns&lt;/th&gt;
    &lt;th&gt;Stored as&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;building, floor, zone, sensor_id&lt;/td&gt;
    &lt;td&gt;Tags&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;temperature_c, humidity_pct, pm25_ug_m3, power_kw&lt;/td&gt;
    &lt;td&gt;Float fields&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;co2_ppm, occupancy, capacity&lt;/td&gt;
    &lt;td&gt;Integer fields&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;time&lt;/td&gt;
    &lt;td&gt;Timestamp&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Keeping the raw and derived data separate makes the model easy to audit. You can inspect the original readings without reverse-engineering a transformed table, while Grafana can query the already classified states.&lt;/p&gt;

&lt;h4 id="test-the-plugin-before-connecting-it-to-writes"&gt;Test the Plugin Before Connecting it to Writes&lt;/h4&gt;

&lt;p&gt;InfluxDB can run a WAL plugin against a sample row without committing its output. This is the quickest way to catch syntax errors or confirm the scoring logic. The &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/get-started/process/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;Processing Engine testing guide&lt;/a&gt; describes this behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 test wal_plugin \
  --database "$INFLUXDB_DATABASE" \
  --lp "building_telemetry,building=test,floor=1,zone=test,sensor_id=test temperature_c=22.0,humidity_pct=45.0,co2_ppm=1200i,pm25_ug_m3=10.0,power_kw=2.0,occupancy=4i,capacity=10i 1786406400000000000" \
  iaq_assessment.py&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Expected&lt;/strong&gt;: one derived &lt;code class="language-markup"&gt;iaq_assessment&lt;/code&gt; line, no errors, risk score 54, severity &lt;code class="language-markup"&gt;high&lt;/code&gt;, and recommendation &lt;code class="language-markup"&gt;increase_ventilation&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The risk is 54 because CO₂ contributes 50 points, PM2.5 contributes 4, and temperature and humidity add zero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistake to avoid&lt;/strong&gt;: The final argument is relative to the server’s &lt;code class="language-markup"&gt;--plugin-dir&lt;/code&gt;, not your terminal’s current directory. Because the server started with plugins as its plugin directory, the correct value is &lt;code class="language-markup"&gt;iaq_assessment.py&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id="create-the-trigger-and-ingest-sample-data"&gt;Create the Trigger and Ingest Sample Data&lt;/h4&gt;

&lt;p&gt;Create a WAL trigger that watches only the raw table:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;export INFLUXDB_TRIGGER="smart_building_iaq_assessment"
influxdb3 create trigger \
  --database "$INFLUXDB_DATABASE" \
  --path iaq_assessment.py \
  --trigger-spec "table:building_telemetry" \
  --error-behavior disable \
  "$INFLUXDB_TRIGGER"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The table scope is important. The plugin writes to &lt;code class="language-markup"&gt;iaq_assessment&lt;/code&gt;; because the trigger watches only &lt;code class="language-markup"&gt;building_telemetry&lt;/code&gt;, those derived writes cannot invoke the plugin recursively. The code also ignores batches from other tables as a second guard.&lt;/p&gt;

&lt;p&gt;Write all 12,096 source rows:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 write \
  --database "$INFLUXDB_DATABASE" \
  --precision s \
  --file smart-building.lp&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;InfluxDB acknowledges the source write separately from completing asynchronous Processing Engine work. Poll the derived count for up to 60 seconds:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;derived_rows=0
for attempt in $(seq 1 60); do
  derived_rows=$(
    influxdb3 query \
      --database "$INFLUXDB_DATABASE" \
      --format csv \
      "SELECT COUNT(*) AS derived_rows FROM iaq_assessment" |
      tail -n 1
  )

  if [[ "$derived_rows" == "12096" ]]; then
    break
  fi

  sleep 1
done

printf 'Derived rows: %s\n' "$derived_rows"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Expected:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;Derived rows: 12096&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the count does not reach 12,096, do not continue to Grafana yet. Review the troubleshooting section and inspect the InfluxDB terminal for Processing Engine errors.&lt;/p&gt;

&lt;p&gt;Disable the trigger after enrichment finishes:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 disable trigger \
  --database "$INFLUXDB_DATABASE" \
  "$INFLUXDB_TRIGGER"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In a real streaming application, you would normally leave a healthy trigger enabled so future writes are enriched.&lt;/p&gt;

&lt;h4 id="query-the-results-with-sql"&gt;Query the Results with SQL&lt;/h4&gt;

&lt;p&gt;Start by validating the raw table:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 query \
  --database "$INFLUXDB_DATABASE" \
  "SELECT
     COUNT(*) AS source_rows,
     COUNT(DISTINCT building) AS buildings,
     COUNT(DISTINCT zone) AS zones,
     MIN(time) AS first_time,
     MAX(time) AS last_time
   FROM building_telemetry"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Expected values:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;source_rows: 12096
buildings: 2
zones: 6
first_time: 2026-08-10T00:00:00
last_time: 2026-08-16T23:55:00&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now summarize the derived table:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 query \
  --database "$INFLUXDB_DATABASE" \
  "SELECT
     COUNT(*) AS derived_rows,
     MIN(risk_score) AS min_risk,
     MAX(risk_score) AS max_risk,
     SUM(
       CASE
         WHEN severity IN ('high', 'critical') AND occupied THEN 1
         ELSE 0
       END
     ) AS unhealthy_occupied_intervals,
     ROUND(SUM(energy_waste_kw) * 5.0 / 60.0, 2) AS avoidable_kwh
   FROM iaq_assessment"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Expected values:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;derived_rows: 12096
min_risk: 0
max_risk: 71
unhealthy_occupied_intervals: 62
avoidable_kwh: 9.29&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, find the CO₂ hotspots and empty-zone consumption:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 query \
  --database "$INFLUXDB_DATABASE" \
  "SELECT
     building,
     zone,
     MAX(co2_ppm) AS peak_co2_ppm,
     ROUND(AVG(pm25_ug_m3), 2) AS avg_pm25_ug_m3&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first two rows should be &lt;code class="language-markup"&gt;hq/conference_a&lt;/code&gt; at 1,770 ppm and &lt;code class="language-markup"&gt;annex/design_studio&lt;/code&gt; at 1,572 ppm. The &lt;code class="language-markup"&gt;hq/lab&lt;/code&gt; row should have the largest raw empty-zone consumption at 61.22 kWh.&lt;/p&gt;

&lt;h2 id="installing-grafana"&gt;Installing Grafana&lt;/h2&gt;

&lt;p&gt;Install Grafana OSS from Grafana Labs’ signed APT repository:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;sudo apt-get install -y apt-transport-https wget gnupg

sudo mkdir -p /etc/apt/keyrings
sudo wget -O /etc/apt/keyrings/grafana.asc \
  https://apt.grafana.com/gpg-full.key
sudo chmod 644 /etc/apt/keyrings/grafana.asc

echo "deb [signed-by=/etc/apt/keyrings/grafana.asc] https://apt.grafana.com stable main" |
  sudo tee /etc/apt/sources.list.d/grafana.list

sudo apt-get update
sudo apt-get install -y grafana&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Start Grafana and enable it at boot:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;sudo systemctl daemon-reload
sudo systemctl enable --now grafana-server.service
sudo systemctl status --no-pager grafana-server.service&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Open &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt; in your browser. On a new installation, the default username and password are both admin; Grafana immediately prompts you to choose a new password.&lt;/p&gt;

&lt;p&gt;Use a unique local password supplied as &lt;code class="language-markup"&gt;$GRAFANA_ADMIN_PASSWORD&lt;/code&gt;. Never reuse the InfluxDB token as a Grafana password.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/23hMx8HAxiYLKCbq8davHr/ec7c0d5bd384ab4c367bde047d86da68/0dc52148-672c-40bf-90ec-e6b6df97cabc.png" alt="InfluxDB 3 and Grafana 1" /&gt;&lt;/p&gt;

&lt;h4 id="create-a-read-only-token-for-grafana"&gt;Create a Read-Only Token for Grafana&lt;/h4&gt;

&lt;p&gt;Grafana only needs to query this one database. It should not receive the administrator token used for setup.&lt;/p&gt;

&lt;p&gt;In the terminal where &lt;code class="language-markup"&gt;INFLUXDB3_AUTH_TOKEN&lt;/code&gt; is still set, run:&lt;/p&gt;

&lt;p&gt;influxdb3 create token \
  –permission “db:smart_building:read” \
  –name “Grafana read-only access to smart_building”&lt;/p&gt;

&lt;p&gt;Store the returned value in your password manager as &lt;code class="language-markup"&gt;$INFLUXDB_GRAFANA_TOKEN&lt;/code&gt;. InfluxDB’s &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/admin/tokens/resource/create/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;resource-token documentation&lt;/a&gt; explains the &lt;code class="language-markup"&gt;db:"database":read&lt;/code&gt; permission format.&lt;/p&gt;

&lt;p&gt;Do not paste this token into a text file or include it in a screenshot. Enter it once in Grafana’s secure token field.&lt;/p&gt;

&lt;h4 id="connect-grafana-to-influxdb-3"&gt;Connect Grafana to InfluxDB 3&lt;/h4&gt;

&lt;p&gt;In Grafana:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open &lt;strong&gt;Connections → datasources&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Click &lt;strong&gt;Add new datasource&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Select &lt;strong&gt;InfluxDB&lt;/strong&gt;. This is the built-in datasource; do not install another plugin.&lt;/li&gt;
  &lt;li&gt;Enter &lt;code class="language-markup"&gt;InfluxDB 3 Smart Building&lt;/code&gt; as the name.&lt;/li&gt;
  &lt;li&gt;Configure the connection:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Setting&lt;/th&gt;
    &lt;th&gt;Value&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;URL&lt;/td&gt;
    &lt;td&gt;http://127.0.0.1:8181&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Query language&lt;/td&gt;
    &lt;td&gt;SQL&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Database&lt;/td&gt;
    &lt;td&gt;smart_building&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Token&lt;/td&gt;
    &lt;td&gt;The securely stored $INFLUXDB_GRAFANA_TOKEN value&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Insecure Connection&lt;/td&gt;
    &lt;td&gt;Enabled&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Click &lt;strong&gt;Save &amp;amp; test&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SQL uses Flight SQL over gRPC. Because both programs are on the same machine and the URL uses local HTTP without TLS, &lt;strong&gt;Insecure Connection&lt;/strong&gt; is required. This setting disables gRPC TLS; it is not a recommendation for traffic crossing an untrusted network.&lt;/p&gt;

&lt;p&gt;The URL is interpreted by the Grafana server, not by your browser. &lt;code class="language-markup"&gt;127.0.0.1&lt;/code&gt; works here because Grafana and InfluxDB run on the same machine. If you later move either service into a container or another machine, update the URL to an address reachable from the Grafana backend while keeping the connection private.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/1my3gCZyflm5Y4KeiqZ6CI/767f7fd0bc9a6186cd4a9e0cc685c135/2fbe33f9-0c51-4b9b-bb21-e50f656579fa.png" alt="InfluxDB 3 and Grafana 2" /&gt;&lt;/p&gt;

&lt;h4 id="create-the-grafana-dashboard-and-variables"&gt;Create the Grafana Dashboard and Variables&lt;/h4&gt;

&lt;p&gt;Create the dashboard first:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open &lt;strong&gt;Dashboards&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Click &lt;strong&gt;New → New Dashboard&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Save it as &lt;strong&gt;Smart Building Operations&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Set the dashboard timezone to &lt;strong&gt;UTC&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Set the absolute time range from &lt;code class="language-markup"&gt;2026-08-10 00:00:00&lt;/code&gt; through &lt;code class="language-markup"&gt;2026-08-17 00:00:00&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The fixed range matters because this is historical data generated in a specific time range. A relative range such as “Last 7 days” will not include it.&lt;/p&gt;

&lt;h4 id="add-the-building-variable"&gt;Add the Building Variable&lt;/h4&gt;

&lt;p&gt;While editing the dashboard, click &lt;strong&gt;Add → Variable&lt;/strong&gt; and configure:&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Option&lt;/th&gt;
    &lt;th&gt;Value&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;Variable type&lt;/td&gt;
    &lt;td&gt;Query&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Name&lt;/td&gt;
    &lt;td&gt;&lt;code&gt;building&lt;/code&gt;&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Label&lt;/td&gt;
    &lt;td&gt;Building&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;datasource&lt;/td&gt;
    &lt;td&gt;InfluxDB 3 Smart Building&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Multi-value&lt;/td&gt;
    &lt;td&gt;Enabled&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Include All&lt;/td&gt;
    &lt;td&gt;Enabled&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Use this SQL query:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT DISTINCT
  building AS __text,
  building AS __value
FROM building_telemetry
ORDER BY building&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The preview should show &lt;code class="language-markup"&gt;annex&lt;/code&gt; and &lt;code class="language-markup"&gt;hq&lt;/code&gt;. Save the variable.&lt;/p&gt;

&lt;h4 id="add-the-zone-variable"&gt;Add the Zone Variable&lt;/h4&gt;

&lt;p&gt;Add another query variable:&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Option&lt;/th&gt;
    &lt;th&gt;Value&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;Name&lt;/td&gt;
    &lt;td&gt;&lt;code&gt;zone&lt;/code&gt;&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Label&lt;/td&gt;
    &lt;td&gt;Zone&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;datasource&lt;/td&gt;
    &lt;td&gt;InfluxDB 3 Smart Building&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Multi-value&lt;/td&gt;
    &lt;td&gt;Enabled&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Include All&lt;/td&gt;
    &lt;td&gt;Enabled&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT DISTINCT
  zone AS __text,
  zone AS __value
FROM building_telemetry
WHERE building IN (${building:sqlstring})
ORDER BY zone&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a chained variable: changing Building refreshes the relevant Zone choices. For multi-value SQL variables, use &lt;code class="language-markup"&gt;IN&lt;/code&gt; and &lt;code class="language-markup"&gt;${variable:sqlstring}&lt;/code&gt;. Grafana supplies correctly quoted SQL strings; do not add another pair of quotes around the variable. See &lt;a href="https://grafana.com/docs/grafana/latest/datasources/influxdb/template-variables/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;InfluxDB template variables&lt;/a&gt; for more examples.&lt;/p&gt;

&lt;p&gt;Set both variables to &lt;strong&gt;All&lt;/strong&gt; before creating the panels.&lt;/p&gt;

&lt;h2 id="building-the-grafana-dashboard-panels"&gt;Building the Grafana dashboard panels&lt;/h2&gt;

&lt;p&gt;For each panel, click &lt;strong&gt;Add → Visualization,&lt;/strong&gt; select &lt;strong&gt;InfluxDB 3 Smart Building&lt;/strong&gt;, switch the query 
editor to SQL code mode if necessary, paste the query, choose the indicated format and visualization, then apply the panel.&lt;/p&gt;

&lt;p&gt;Every query uses two Grafana features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;$__timeFilter(time)&lt;/code&gt; expands to the dashboard’s active time range.&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;${building:sqlstring}&lt;/code&gt; and &lt;code class="language-markup"&gt;${zone:sqlstring}&lt;/code&gt; expand the multi-select variables into quoted SQL values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grafana documents the available SQL macros in its &lt;a href="https://grafana.com/docs/grafana/latest/datasources/influxdb/query-editor/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;InfluxDB query editor reference&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id="peak-co-dashboard"&gt;Peak CO₂ Dashboard&lt;/h4&gt;

&lt;p&gt;This stat answers, “What was the highest CO₂ reading in the selected scope?”&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT MAX(co2_ppm) AS "Peak CO₂ ppm"
FROM building_telemetry
WHERE $__timeFilter(time)
  AND building IN (${building:sqlstring})
  AND zone IN (${zone:sqlstring})&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visualization: &lt;strong&gt;Stat&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Format: &lt;strong&gt;Table&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Unit: &lt;strong&gt;ppm&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Title: &lt;strong&gt;Peak CO₂&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all buildings and zones selected, expect 1,770 ppm.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/5Jlq6geUXEzBO7Iaj0Xl7r/6fdb2591da2147c97b38e9f90322a637/c639889b-2964-473d-b275-d62bc14ec884.png" alt="InfluxDB 3 and Grafana 3" /&gt;&lt;/p&gt;

&lt;p&gt;Keep the color neutral unless you have documented, context-appropriate CO₂ thresholds. A peak value alone does not describe duration, sensor accuracy, or local health policy.&lt;/p&gt;

&lt;h4 id="unhealthy-occupied-intervals-dashboard"&gt;Unhealthy Occupied Intervals Dashboard&lt;/h4&gt;

&lt;p&gt;This panel counts five-minute zone intervals that the plugin classified as high or critical while someone was present:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT COUNT(*) AS "Unhealthy occupied intervals"
FROM iaq_assessment
WHERE $__timeFilter(time)
  AND building IN (${building:sqlstring})
  AND zone IN (${zone:sqlstring})
  AND severity IN ('high', 'critical')
  AND occupied = true&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visualization: &lt;strong&gt;Stat&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Format: &lt;strong&gt;Table&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Unit: short&lt;/li&gt;
  &lt;li&gt;Title: &lt;strong&gt;Unhealthy occupied intervals&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expected result: 62. This means 62 five-minute zone records, not 62 separate incidents.&lt;/p&gt;

&lt;h4 id="energy-while-empty-dashboard"&gt;Energy While Empty Dashboard&lt;/h4&gt;

&lt;p&gt;The source cadence is five minutes, so kWh for one row is &lt;code class="language-markup"&gt;power_kw × 5/60&lt;/code&gt;. This query integrates every interval with zero occupancy:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT ROUND(
  SUM(
    CASE
      WHEN occupancy = 0 THEN power_kw * 5.0 / 60.0
      ELSE 0
    END
  ),
  2
) AS "Empty-zone kWh"
FROM building_telemetry
WHERE $__timeFilter(time)
  AND building IN (${building:sqlstring})
  AND zone IN (${zone:sqlstring})&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visualization: &lt;strong&gt;Stat&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Format: &lt;strong&gt;Table&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Unit: &lt;strong&gt;kWh&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Title: &lt;strong&gt;Energy while empty&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id="co-by-zone-dashboard"&gt;CO₂ by Zone Dashboard&lt;/h4&gt;

&lt;p&gt;A raw five-minute series is readable, but a 15-minute average makes the incident shape easier to compare across zones:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT
  date_bin(
    INTERVAL '15 minutes',
    time,
    TIMESTAMP '1970-01-01T00:00:00Z'
  ) AS time,
  zone,
  AVG(co2_ppm) AS "CO₂ ppm"
FROM building_telemetry
WHERE $__timeFilter(time)
  AND building IN (${building:sqlstring})
  AND zone IN (${zone:sqlstring})
GROUP BY 1, 2
ORDER BY 1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visualization: &lt;strong&gt;Time series&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Format: &lt;strong&gt;Time series&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Unit: ppm&lt;/li&gt;
  &lt;li&gt;Legend: table, with maximum displayed&lt;/li&gt;
  &lt;li&gt;Title: &lt;strong&gt;CO₂ by zone&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result contains 672 series rows: 112 quarter-hour bins × six zones. A time series query must return a timestamp column; naming it time keeps the Grafana mapping straightforward.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/26p6fhSvn9DqLvFPSMbmqN/ef63172e1dc7bbdc1ca706344ae46a82/63d5c6b0-60b9-4b89-8972-e155d9fdc855.png" alt="InfluxDB 3 and Grafana 4" /&gt;&lt;/p&gt;

&lt;h4 id="indoor-air-quality-state-dashboard"&gt;Indoor Air Quality State Dashboard&lt;/h4&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT time, zone, severity
FROM iaq_assessment
WHERE $__timeFilter(time)
  AND building IN (${building:sqlstring})
  AND zone IN (${zone:sqlstring})
ORDER BY time&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visualization: &lt;strong&gt;State timeline&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Format: &lt;strong&gt;Time series&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Title: &lt;strong&gt;Indoor-air-quality state&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add value mappings:&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Value&lt;/th&gt;
    &lt;th&gt;Label&lt;/th&gt;
    &lt;th&gt;Suggested color&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;&lt;code&gt;normal&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;Normal&lt;/td&gt;
    &lt;td&gt;Green&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;&lt;code&gt;moderate&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;Moderate&lt;/td&gt;
    &lt;td&gt;Yellow&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;&lt;code&gt;high&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;High&lt;/td&gt;
    &lt;td&gt;Orange&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;&lt;code&gt;critical&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;Critical&lt;/td&gt;
    &lt;td&gt;Red&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;h4 id="wasted-energy-dashboard"&gt;Wasted Energy Dashboard&lt;/h4&gt;

&lt;p&gt;The plugin’s energy signal shows how much power exceeded the 1.5 kW baseline while the zone was empty.&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT
  date_bin(
    INTERVAL '15 minutes',
    time,
    TIMESTAMP '1970-01-01T00:00:00Z'
  ) AS time,
  zone,
  AVG(energy_waste_kw) AS "Excess kW wasted"
FROM iaq_assessment
WHERE $__timeFilter(time)
  AND building IN (${building:sqlstring})
  AND zone IN (${zone:sqlstring})
GROUP BY 1, 2
ORDER BY 1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visualization: &lt;strong&gt;Time series&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Format: &lt;strong&gt;Time series&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Draw style: bars&lt;/li&gt;
  &lt;li&gt;Stacking: normal&lt;/li&gt;
  &lt;li&gt;Unit: &lt;code class="language-markup"&gt;kW&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Title: &lt;strong&gt;Energy wasted&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The derived weekly total is 9.29 kWh, concentrated in the lab’s Wednesday evening event. Panel 3’s 316.04 kWh and this 9.29 kWh are intentionally different—the second number is more conservative.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/5FJh5uuI4xD5lNIsypoI1L/7f57e792c902d8637c01c7f2206c8ff4/957a8adc-6ea9-4ec8-89f2-be452b3d0a0f.png" alt="InfluxDB 3 and Grafana 5" /&gt;&lt;/p&gt;

&lt;h4 id="risk-by-zone-dashboard"&gt;Risk by Zone Dashboard&lt;/h4&gt;

&lt;p&gt;This query compares each zone’s normal operating level with its worst interval:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT
  zone,
  ROUND(AVG(risk_score), 1) AS "Average risk",
  MAX(risk_score) AS "Peak risk"
FROM iaq_assessment
WHERE $__timeFilter(time)
  AND building IN (${building:sqlstring})
  AND zone IN (${zone:sqlstring})
GROUP BY zone
ORDER BY "Peak risk" DESC&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visualization: &lt;strong&gt;Bar gauge&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Format: &lt;strong&gt;Table&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Minimum: &lt;strong&gt;0&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Maximum: &lt;strong&gt;100&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Unit: &lt;strong&gt;none&lt;/strong&gt;—the score is bounded from 0 to 100 but is not a percentage&lt;/li&gt;
  &lt;li&gt;Title: &lt;strong&gt;Risk by zone&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/2yof0RI2DgWBhP4fw5K118/54fa0fdf1874038d7f36f2bd4f0a3fb3/46780643-dcb0-46ad-aa99-6345b4442361.png" alt="InfluxDB 3 and Grafana 6" /&gt;&lt;/p&gt;

&lt;h4 id="operational-hotspots-dashboard"&gt;Operational Hotspots Dashboard&lt;/h4&gt;

&lt;p&gt;Finish with a table that puts ventilation and energy context together:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT
  building,
  zone,
  MAX(co2_ppm) AS peak_co2_ppm,
  ROUND(AVG(pm25_ug_m3), 1) AS avg_pm25,
  ROUND(
    SUM(CASE WHEN occupancy = 0 THEN power_kw * 5.0 / 60.0 ELSE 0 END),
    2
  ) AS empty_zone_kwh
FROM building_telemetry
WHERE $__timeFilter(time)
  AND building IN (${building:sqlstring})
  AND zone IN (${zone:sqlstring})
GROUP BY building, zone
ORDER BY peak_co2_ppm DESC&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visualization: &lt;strong&gt;Table&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Format: &lt;strong&gt;Table&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Sort: &lt;code class="language-markup"&gt;peak_co2_ppm&lt;/code&gt;, descending&lt;/li&gt;
  &lt;li&gt;Title: &lt;strong&gt;Operational hotspots&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The table should contain six rows. conference_a ranks first for CO₂, while the lab leads in raw empty-zone energy, a useful reminder that air quality and energy efficiency reveal different operational problems. Save the dashboard after adding all eight panels.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/6YJqNgPGe7DkBc6PTWEr0Q/f4b74aeb992426952ac223247b8c0e7d/0ea255c9-2f4e-44e6-9ed3-bf34a6592cd1.png" alt="InfluxDB 3 and Grafana 7" /&gt;&lt;/p&gt;

&lt;h2 id="where-to-take-the-project-next"&gt;Where to take the project next?&lt;/h2&gt;

&lt;p&gt;You now have a complete InfluxDB 3 and Grafana stack running locally. Telemetry is written as line protocol, with a Python plugin enriching every row as it lands, a derived table storing decisions rather than measurements, and a Grafana dashboard querying both.
The pattern is worth more than just this project. The plugin is roughly fifty lines of standard-library Python. The trigger is table-scoped so it cannot recurse. The raw table is untouched, so if you decide next month that 800 ppm was the wrong CO₂ threshold, you can rewrite the scoring and recompute from source. And because the enrichment happens once at write time, every dashboard panel stays a short, readable query.&lt;/p&gt;

&lt;h4 id="grafana-features-to-try"&gt;Grafana Features to Try&lt;/h4&gt;

&lt;p&gt;You built eight panels in this tutorial, but that’s only a fraction of what Grafana can do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Transformations&lt;/strong&gt; - Join &lt;code class="language-markup"&gt;building_telemetry&lt;/code&gt; and &lt;code class="language-markup"&gt;iaq_assessment&lt;/code&gt; on time and zone, then use Organize fields and Add field from calculation to build a combined table without writing a more complex SQL query.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Data links and drill-downs&lt;/strong&gt; - Turn each row of the Operational hotspots table into a link that opens a zone-scoped view with the zone variable pre-set. It’s a two-minute change that makes the dashboard feel like an application.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Ad hoc filters&lt;/strong&gt; - An ad hoc filter variable lets viewers add their own building = hq style constraints at view time without editing any query.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Canvas and Geomap&lt;/strong&gt; - Canvas can overlay live severity colors on a floor plan image; Geomap does the same on a real map if your zones carry coordinates. Both are far more legible to non-technical stakeholders than a time series.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Explore mode&lt;/strong&gt; - Prototype SQL against the datasource without creating a panel first—the fastest way to iterate on a query.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Dashboards as code&lt;/strong&gt; - Export the dashboard JSON and check it into version control, or use Grafana provisioning to deploy the datasource and dashboard together on a fresh machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id="influxdb-3-features-to-try"&gt;InfluxDB 3 Features to Try&lt;/h4&gt;

&lt;p&gt;The Processing Engine plugin you wrote is one trigger type among several, and InfluxDB has caching and lifecycle features that pair directly with what you just built:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Scheduled triggers&lt;/strong&gt; - WAL triggers run inline on the write path, so they should stay cheap. A scheduled trigger runs on an interval or cron expression instead. These are great for hourly and daily rollups, anomaly detection over a window, or anything that needs to look across many rows rather than one.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Rollup tables&lt;/strong&gt; - Have a scheduled trigger write a &lt;code class="language-markup"&gt;zone_hourly&lt;/code&gt; summary. Dashboards over long ranges then read a small pre-aggregated table instead of scanning weeks of five-minute data.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;HTTP request triggers&lt;/strong&gt; - Expose a plugin at an endpoint, and you have a small API—a current-status lookup for a room display, or a webhook that returns the top three zones to investigate.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Last Value Cache&lt;/strong&gt; - Keeps the most recent value per series in memory for very fast lookups, which suits “current state” stat panels and real-time displays far better than a &lt;code class="language-markup"&gt;MAX(time)&lt;/code&gt; subquery.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Distinct Value Cache&lt;/strong&gt; - Speeds up exactly the kind of query your Building and Zone template variables run, like &lt;code class="language-markup"&gt;SELECT DISTINCT&lt;/code&gt; over a tag column. On a large deployment, this is the difference between dashboards that load instantly and dashboards that stall on variable refresh.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Retention periods&lt;/strong&gt; - Set a retention period on the database so raw five-minute data expires while your rollup table keeps the long history. This is the standard way to control storage cost in time series systems.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;InfluxDB 3 Explorer&lt;/strong&gt; - A browser UI for browsing databases and prototyping queries, handy when you want to check a table’s shape without dropping into the CLI.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="get-started-with-influxdb-3-and-grafana"&gt;Get started with InfluxDB 3 and Grafana&lt;/h2&gt;

&lt;p&gt;If you have not set up InfluxDB 3 yet, start a free InfluxDB 3 Enterprise trial or download InfluxDB 3 Core from the InfluxData downloads page, then follow the &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/install/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;installation guide&lt;/a&gt;. The full Processing Engine reference is in the &lt;a href="https://docs.influxdata.com/influxdb3/enterprise/plugins/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;InfluxDB 3 documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Built something with this pattern? A different plugin, a better scoring model, a dashboard for a domain we didn’t think of? Share it in the &lt;a href="https://community.influxdata.com/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=getting_started_influxdb_3_grafana&amp;amp;utm_content=blog"&gt;InfluxData Community forums&lt;/a&gt;. Questions are welcome there too.&lt;/p&gt;
</description>
      <pubDate>Wed, 02 Sep 2026 07:00:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/getting-started-influxdb-3-grafana/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/getting-started-influxdb-3-grafana/</guid>
      <category>Getting Started</category>
      <category>Developer</category>
      <author>Charles Mahler (InfluxData)</author>
    </item>
    <item>
      <title>Telegraf Controller 1.1: Make Fleet-Wide Config Changes with a Single Edit</title>
      <description>&lt;p&gt;Telegraf is easy to stand up. You just need a config file with a few plugins and data flows. That ease is why Telegraf fleets grow fast, and why managing the agents that collect data becomes more difficult than collecting it. A change that takes minutes on ten agents takes days across a few hundred. Telegraf Controller is a centralized control plane for managing, configuring, and monitoring your fleet of Telegraf agents.&lt;/p&gt;

&lt;p&gt;Telegraf Controller 1.1 is available today and addresses that management problem from two sides: keeping the Controller layer itself reliable, and making fleet-wide changes without touching every config. The release adds high availability, configuration versioning, global constants, configuration groups, and aliases.&lt;/p&gt;

&lt;h2 id="high-availability-telegraf-enterprise"&gt;High availability (Telegraf Enterprise)&lt;/h2&gt;

&lt;p&gt;High availability lets you run multiple Controller instances from a shared database with automatic failover. If an instance goes down, agents keep pulling configuration and reporting health through the remaining instances.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/39kyCk4mF4jPhZihpQEirg/2c54ea056b699631c5380005a5686dcd/da520a75-dae5-4f92-85ec-f23ebd5579c7.png" alt="Telegraf Controller 1.1 graphic 1" /&gt;&lt;/p&gt;

&lt;p&gt;For production monitoring, compliance systems, and other mission-critical pipelines, the configuration layer needs to meet the same reliability requirements as the rest of the stack. High availability also simplifies planned maintenance: one instance can go offline for patching and the config path stays open. In strict environments that require redundancy, it also removes Controller as a single point of failure.&lt;/p&gt;

&lt;h2 id="configuration-versioning"&gt;Configuration versioning&lt;/h2&gt;

&lt;p&gt;Configuration versioning saves every configuration change as a new version, including who made it. If an edit causes errors, compare the current version against the previous one in a side-by-side, color-coded diff and revert.&lt;/p&gt;

&lt;p&gt;&lt;img src="//images.ctfassets.net/o7xu9whrs0u9/Jky3U3WlEzmdvEWtySoM1/3845319032a3fc7472af30c1200ca2ca/b67ee017-6cdb-499b-bba3-bf6d676bd2d9.png" alt="Telegraf Controller 1.1 graphic 2" /&gt;&lt;/p&gt;

&lt;p&gt;Configuration history also provides an  audit trail. Teams can trace when individual settings changed and test tuning changes without losing the last working configuration.&lt;/p&gt;

&lt;h2 id="global-constants"&gt;Global constants&lt;/h2&gt;

&lt;p&gt;Global constants let you define a value once (an output endpoint, a collection interval, a region name) and reference it from any configuration; updating the constant updates every configuration that references it.&lt;/p&gt;

&lt;p&gt;Reference a constant anywhere in a configuration with the &lt;code class="language-markup"&gt;::{constant_name}&lt;/code&gt; syntax. When Controller serves a configuration to an agent, it resolves each reference to the constant’s current value:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;[agent]
  interval = "::{collection_interval}"

[[outputs.influxdb_v3]]
  urls = ["::{influxdb_url}"]
  token = "${INFLUX_TOKEN}"
  database = "::{metrics_database}"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The immediate benefit is consistency: shared values live in one place instead of being duplicated across dozens of configurations and drifting out of sync. Constants also simplify migrations: moving your fleet to a new output endpoint or standardizing collection intervals across teams becomes one edit instead of a config-by-config sweep.&lt;/p&gt;

&lt;h2 id="configuration-groups"&gt;Configuration groups&lt;/h2&gt;

&lt;p&gt;Configuration groups bundle multiple configurations into an ordered unit that agents retrieve in a single request. Instead of assigning each agent its own stack of individual configs, you assign the group.&lt;/p&gt;

&lt;p&gt;Groups compose by reference, not by copy. A config can belong to multiple groups, and editing a config propagates the change to every group that includes it.&lt;/p&gt;

&lt;p&gt;That’s what makes groups work as role profiles. Build one base config with the system inputs every host runs, then compose it with the configs specific to a web server or a database host. Tune the base config once and every role updates without maintaining separate copies that can drift. Groups also serve as templates. A group proven in production becomes the starting point for the next site or deployment, instead of another copy-paste job.&lt;/p&gt;

&lt;h2 id="configuration-aliases"&gt;Configuration aliases&lt;/h2&gt;

&lt;p&gt;Configuration aliases let you use custom, human-readable identifiers for configs in both the UI and the API. Agents request &lt;code class="language-markup"&gt;web-baseline&lt;/code&gt; instead of a UUID, so when it’s time to move agents to a different config, simply move the alias and the fleet cuts over on the next pull.&lt;/p&gt;

&lt;p&gt;If you are running multiple Controllers use a single alias to reference the same config on each instance rather than config UUIDs, which are unique to each Controller.&lt;/p&gt;

&lt;h2 id="one-change-fleet-wide"&gt;One change, fleet-wide&lt;/h2&gt;

&lt;p&gt;Constants, groups, and aliases are each useful on their own, but they’re designed to work together. If every site’s agents request the same group by alias, and that group’s configurations pull shared values from global constants, a fleet-wide change—a new endpoint or interval—is a single edit. Every site picks it up on its next config pull.&lt;/p&gt;

&lt;h2 id="whats-free-and-what-requires-telegraf-enterprise"&gt;What’s free and what requires Telegraf Enterprise&lt;/h2&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Feature&lt;/th&gt;
    &lt;th&gt;Free&lt;/th&gt;
    &lt;th&gt;Enterprise&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;High availability&lt;/td&gt;
    &lt;td style="color:#e02b2b; font-weight:bold;"&gt;No&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Configuration versioning&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Configuration aliases&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Global constants&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Configuration groups&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
    &lt;td style="color:#6a9a4d; font-weight:bold;"&gt;Yes&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;h2 id="get-started"&gt;Get started&lt;/h2&gt;

&lt;p&gt;The value of Telegraf Controller 1.1 is a config path that stays up and is far less work to keep the fleet current. High availability maintains uptime through instance failures, so the layer serving your configs meets the same reliability as the rest of your stack. Shared values are defined once instead of copied across every config, and config changes reach the whole fleet on the next pull with a record of what moved and an easy revert if something went wrong.&lt;/p&gt;

&lt;p&gt;Telegraf Controller 1.1 is available today. &lt;a href="https://docs.influxdata.com/telegraf/controller/install/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_controller_1_1&amp;amp;utm_content=blog"&gt;Download and install Telegraf Controller&lt;/a&gt; for free or &lt;a href="https://www.influxdata.com/contact-sales-telegraf-enterprise/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=telegraf_controller_1_1&amp;amp;utm_content=blog"&gt;contact us about Telegraf Enterprise&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="faq"&gt;FAQ&lt;/h2&gt;

&lt;div id="accordion_second"&gt;
    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-1"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;What's new in Telegraf Controller 1.1?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-1" class="message-body is-collapsible is-active" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Telegraf Controller 1.1 adds high availability (Enterprise only), configuration versioning, global constants, configuration groups, and configuration aliases. Together, these allow a single edit, like a new output endpoint or collection interval, propagate across an entire fleet on the next agent config pull.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-2"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How does high availability work in Telegraf Controller?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-2" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                High availability lets you run multiple Telegraf Controller instances against a shared database with automatic failover. If one instance goes down, agents keep pulling their configuration and reporting health through the remaining instances.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-3"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How do global constants work in Telegraf Controller?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-3" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Global constants let you define a value once (i.e. an output endpoint, collection interval, or region name) and reference it from any configuration using ::{constant_name} syntax. When Controller serves a config to an agent, it resolves the reference to the constant's current value, so updating the constant updates every configuration that uses it.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

&lt;/div&gt;
</description>
      <pubDate>Tue, 25 Aug 2026 00:25:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/telegraf-controller-1-1/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/telegraf-controller-1-1/</guid>
      <category>Product</category>
      <category>Developer</category>
      <author>Scott Anderson (InfluxData)</author>
    </item>
    <item>
      <title>A Guide to Downsampling Time Series Data with InfluxDB 3</title>
      <description>&lt;p&gt;This tutorial demonstrates both approaches using the InfluxDB 3 Processing Engine’s built-in bird tracking simulator plugin. You will generate telemetry, aggregate it into 10-second windows, and validate the result with SQL. The same pattern works for infrastructure metrics, industrial sensors, application telemetry, and other time series workloads.&lt;/p&gt;

&lt;h2 id="why-downsample-time-series-data"&gt;Why downsample time series data?&lt;/h2&gt;

&lt;p&gt;High-resolution data is valuable while diagnosing a recent event, but its value often changes as it ages. A temperature reading collected every second may be useful for an active incident, while a daily report may only need 10-minute or hourly averages.&lt;/p&gt;

&lt;p&gt;Downsampling helps you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;scan fewer rows in long-range queries&lt;/li&gt;
  &lt;li&gt;make dashboards over weeks or months more responsive&lt;/li&gt;
  &lt;li&gt;retain useful historical trends at a lower resolution, reducing storage costs&lt;/li&gt;
  &lt;li&gt;calculate common summaries once instead of repeating the work&lt;/li&gt;
  &lt;li&gt;keep raw data only for as long as its full resolution is useful&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Downsampling is not the same as deleting raw data; it creates a summarized view or table at a lower granularity. Retention is a separate decision and process where data is fully deleted after a set period of time.&lt;/p&gt;

&lt;h4 id="choose-query-time-or-persisted-downsampling"&gt;Choose Query-Time or Persisted Downsampling&lt;/h4&gt;

&lt;p&gt;InfluxDB 3 gives you two practical patterns for downsampling:&lt;/p&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Approach&lt;/th&gt;
    &lt;th&gt;How it works&lt;/th&gt;
    &lt;th&gt;Best for&lt;/th&gt;
    &lt;th&gt;Main tradeoff&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;Query-time SQL&lt;/td&gt;
    &lt;td&gt;Uses &lt;code&gt;DATE_BIN&lt;/code&gt; and aggregate functions in a &lt;code&gt;SELECT&lt;/code&gt; query&lt;/td&gt;
    &lt;td&gt;Exploration, flexible dashboards, and changing aggregation requirements&lt;/td&gt;
    &lt;td&gt;Recomputes the result each time and does not reduce stored raw data&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;Python Processing Engine&lt;/td&gt;
    &lt;td&gt;Runs the official downsampler plugin on a schedule and writes aggregate rows to a target table&lt;/td&gt;
    &lt;td&gt;Repeated long-range queries, predictable rollups, and tiered retention&lt;/td&gt;
    &lt;td&gt;Requires you to choose aggregates and scheduling behavior in advance&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;A useful starting point is to develop and validate an aggregate in SQL. If the same query becomes a frequent or expensive workload, then use the downsampler plugin.&lt;/p&gt;

&lt;h2 id="prerequisites"&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, you need:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;InfluxDB 3 Core or Enterprise with the Processing Engine enabled&lt;/li&gt;
  &lt;li&gt;InfluxDB 3 CLI installed and connected to the server&lt;/li&gt;
  &lt;li&gt;An authorization token with permission to create a database and triggers&lt;/li&gt;
  &lt;li&gt;Outbound access to GitHub so InfluxDB can load the official plugins referenced by gh: paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The examples assume a database named &lt;code class="language-markup"&gt;bird_demo&lt;/code&gt;:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 create database bird_demo&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you are using the local Docker environment that accompanies this article, InfluxDB is available at &lt;code class="language-markup"&gt;http://localhost:8181&lt;/code&gt;. InfluxDB 3 Explorer is available separately at &lt;code class="language-markup"&gt;http://localhost:8888&lt;/code&gt; for running the SQL and capturing visual results.&lt;/p&gt;

&lt;h4 id="generate-sample-telemetry-with-the-official-bird-simulator"&gt;Generate Sample Telemetry with the Official Bird Simulator&lt;/h4&gt;

&lt;p&gt;InfluxData’s &lt;a href="https://github.com/influxdata/influxdb3_plugins/tree/main/influxdata/bird_data_simulator/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=downsampling_guide_influxdb_3&amp;amp;utm_content=blog"&gt;bird data simulator&lt;/a&gt; is a convenient fit for this tutorial. It creates repeatable time series behavior without requiring a separate data generator or hardware sensor.&lt;/p&gt;

&lt;p&gt;The plugin writes to the &lt;code class="language-markup"&gt;bird_tracking&lt;/code&gt; table. Its tags include species and name, and its fields include &lt;code class="language-markup"&gt;body_temp&lt;/code&gt;, &lt;code class="language-markup"&gt;longitude&lt;/code&gt;, &lt;code class="language-markup"&gt;latitude&lt;/code&gt;, &lt;code class="language-markup"&gt;speed&lt;/code&gt;, and &lt;code class="language-markup"&gt;heading&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, install the plugin’s &lt;code class="language-markup"&gt;Faker&lt;/code&gt; dependency:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 install package Faker&lt;/code&gt;&lt;/pre&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 create trigger \
  --database bird_demo \
  --path gh:influxdata/bird_data_simulator/bird_data_simulator.py \
  --trigger-spec every:1s \
  --trigger-arguments bird_count=10 \
  bird_tracking_demo&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After the trigger has run for several seconds, confirm that data is arriving:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT *
FROM bird_tracking
ORDER BY time DESC
LIMIT 5;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At one write per bird per second, the simulator produces approximately 600 rows per minute for 10 birds.&lt;/p&gt;

&lt;h4 id="downsample-at-query-time-with-sql"&gt;Downsample at Query Time with SQL&lt;/h4&gt;

&lt;p&gt;InfluxDB 3 SQL supports time bucketing with &lt;code class="language-markup"&gt;DATE_BIN()&lt;/code&gt;. The following query groups the raw bird readings into 10-second intervals and calculates speed and body-temperature statistics for each bird:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT
  DATE_BIN(INTERVAL '10 seconds', time) AS time,
  species,
  name,
  AVG(speed) AS avg_speed,
  MIN(speed) AS min_speed,
  MAX(speed) AS max_speed,
  AVG(body_temp) AS avg_body_temp,
  COUNT(*) AS record_count
FROM bird_tracking
WHERE time &amp;gt;= now() - INTERVAL '2 minutes'
GROUP BY 1, species, name
ORDER BY 1 DESC, species, name;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code class="language-markup"&gt;DATE_BIN&lt;/code&gt; aligns each timestamp to a 10-second boundary. &lt;code class="language-markup"&gt;GROUP BY 1&lt;/code&gt; refers to the first expression in the &lt;code class="language-markup"&gt;SELECT&lt;/code&gt; list while &lt;code class="language-markup"&gt;species&lt;/code&gt; and &lt;code class="language-markup"&gt;name&lt;/code&gt; preserve one series per bird.&lt;/p&gt;

&lt;p&gt;This is true query-time downsampling: the server returns fewer, summarized rows, but it does not write them to another table. Change the interval or aggregates whenever the question changes. For example, a long-range dashboard might replace &lt;code class="language-markup"&gt;INTERVAL '10 seconds'&lt;/code&gt; with &lt;code class="language-markup"&gt;INTERVAL '1 hour'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Always include a bounded time predicate. It reduces the data scanned and makes the query’s intended resolution explicit.&lt;/p&gt;

&lt;h4 id="persist-downsampled-data-with-the-python-processing-engine"&gt;Persist Downsampled Data with the Python Processing Engine&lt;/h4&gt;

&lt;p&gt;For an aggregate that many users or dashboards repeatedly request, calculate it on a schedule with InfluxData’s official &lt;a href="https://docs.influxdata.com/influxdb3/core/plugins/library/official/downsampler/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=downsampling_guide_influxdb_3&amp;amp;utm_content=blog"&gt;downsampler plugin&lt;/a&gt;. The plugin queries the source table, computes aggregates, and writes the results to a target table.&lt;/p&gt;

&lt;p&gt;This trigger creates one average speed and body-temperature row per bird for every 10-second interval:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-bash"&gt;influxdb3 create trigger \
  --database bird_demo \
  --path gh:influxdata/downsampler/downsampler.py \
  --trigger-spec every:10s \
  --trigger-arguments \
  'source_measurement=bird_tracking,target_measurement=bird_tracking_10s,interval=10s,window=2min,offset=10s,calculations=speed:avg.body_temp:avg,specific_fields=speed.body_temp' \
  bird_tracking_downsample&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The trigger arguments control the rollup:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;source_measurement&lt;/code&gt; is the raw source table.&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;target_measurement&lt;/code&gt; is the table that receives aggregates&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;interval=10s&lt;/code&gt; defines the time-bin width.&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;calculations&lt;/code&gt; assigns an aggregate function to each field&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;specific_fields&lt;/code&gt; limits processing to the fields needed by this rollup.&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;offset=10s&lt;/code&gt; delays the queried window so its newest bin has time to close.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id="why-the-offset-matters"&gt;Why the Offset Matters&lt;/h4&gt;

&lt;p&gt;The offset is not cosmetic. Without it, the simulator and downsampler could execute on the same 10-second scheduler boundary. Without an offset, the downsampler may query the newest bin while writes are still arriving, producing partial aggregates.&lt;/p&gt;

&lt;p&gt;With &lt;code class="language-markup"&gt;offset=10s&lt;/code&gt;, the preceding completed bin and every aggregate in the validation window should have the expected 10 source points. In production, set the offset to at least the maximum delay you expect between an event occurring and becoming queryable. Workloads with late or out-of-order data may need a larger offset and lookback window.&lt;/p&gt;

&lt;h4 id="inspect-the-persisted-result"&gt;Inspect the Persisted Result&lt;/h4&gt;

&lt;p&gt;The downsampler names calculated fields by appending the aggregate function, so &lt;code class="language-markup"&gt;speed&lt;/code&gt; becomes &lt;code class="language-markup"&gt;speed_avg&lt;/code&gt; and &lt;code class="language-markup"&gt;body_temp&lt;/code&gt; becomes &lt;code class="language-markup"&gt;body_temp_avg&lt;/code&gt;. It also writes &lt;code class="language-markup"&gt;record_count&lt;/code&gt;, &lt;code class="language-markup"&gt;time_from&lt;/code&gt;, and &lt;code class="language-markup"&gt;time_to&lt;/code&gt; metadata.&lt;/p&gt;

&lt;p&gt;The plugin stores the data with nanosecond precision and converts it with &lt;code class="language-markup"&gt;TO_TIMESTAMP_NANOS()&lt;/code&gt; when you want readable timestamps:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT
  time,
  species,
  name,
  ROUND(speed_avg, 2) AS avg_speed_mph,
  ROUND(body_temp_avg, 2) AS avg_body_temp_c,
  record_count,
  TO_TIMESTAMP_NANOS(time_from) AS source_start,
  TO_TIMESTAMP_NANOS(time_to) AS source_end
FROM bird_tracking_10s
ORDER BY time DESC, species, name
LIMIT 20;&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id="sample-output"&gt;Sample Output&lt;/h4&gt;

&lt;div class="blog-html-table-wrapper"&gt;
 &lt;table class="blog-html-table"&gt;
  &lt;thead&gt;
   &lt;tr&gt;
    &lt;th&gt;Time (UTC)&lt;/th&gt;
    &lt;th&gt;Species&lt;/th&gt;
    &lt;th&gt;Bird&lt;/th&gt;
    &lt;th&gt;Avg. speed&lt;/th&gt;
    &lt;th&gt;Avg. body temp.&lt;/th&gt;
    &lt;th&gt;Source points&lt;/th&gt;
    &lt;th&gt;Source start&lt;/th&gt;
   &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td&gt;2026-08-14 21:21:00&lt;/td&gt;
    &lt;td&gt;American Robin&lt;/td&gt;
    &lt;td&gt;Tracy&lt;/td&gt;
    &lt;td&gt;22.47&lt;/td&gt;
    &lt;td&gt;41.94&lt;/td&gt;
    &lt;td&gt;10&lt;/td&gt;
    &lt;td&gt;21:21:00&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;2026-08-14 21:21:00&lt;/td&gt;
    &lt;td&gt;Blue Jay&lt;/td&gt;
    &lt;td&gt;Sara&lt;/td&gt;
    &lt;td&gt;21.59&lt;/td&gt;
    &lt;td&gt;41.67&lt;/td&gt;
    &lt;td&gt;10&lt;/td&gt;
    &lt;td&gt;21:21:00&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;2026-08-14 21:21:00&lt;/td&gt;
    &lt;td&gt;Cactus Wren&lt;/td&gt;
    &lt;td&gt;Brandon&lt;/td&gt;
    &lt;td&gt;18.78&lt;/td&gt;
    &lt;td&gt;41.74&lt;/td&gt;
    &lt;td&gt;10&lt;/td&gt;
    &lt;td&gt;21:21:00&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;2026-08-14 21:21:00&lt;/td&gt;
    &lt;td&gt;Great Blue Heron&lt;/td&gt;
    &lt;td&gt;Brenda&lt;/td&gt;
    &lt;td&gt;6.38&lt;/td&gt;
    &lt;td&gt;41.10&lt;/td&gt;
    &lt;td&gt;10&lt;/td&gt;
    &lt;td&gt;21:21:00&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td&gt;2026-08-14 21:21:00&lt;/td&gt;
    &lt;td&gt;Great Blue Heron&lt;/td&gt;
    &lt;td&gt;Pamela&lt;/td&gt;
    &lt;td&gt;24.97&lt;/td&gt;
    &lt;td&gt;41.35&lt;/td&gt;
    &lt;td&gt;10&lt;/td&gt;
    &lt;td&gt;21:21:00&lt;/td&gt;
   &lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;

&lt;h4 id="validate-the-reduction-with-sql"&gt;Validate the Reduction with SQL&lt;/h4&gt;

&lt;p&gt;Do not judge a downsampling job only by whether the target table contains rows. Compare a fixed, completed interval so active writes cannot change the counts during validation.&lt;/p&gt;

&lt;p&gt;The following query compares two completed minutes of source data with the corresponding persisted rollups. &lt;strong&gt;Replace the timestamps with a completed interval from your own run&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;WITH raw AS (
  SELECT COUNT(*) AS raw_rows, COUNT(DISTINCT name) AS birds
  FROM bird_tracking
  WHERE time &amp;gt;= TIMESTAMP '2026-08-14T21:20:00Z'
    AND time " TIMESTAMP '2026-08-14T21:22:00Z'
),
downsampled AS (
  SELECT
    COUNT(*) AS downsampled_rows,
    SUM(record_count) AS represented_raw_rows,
    AVG(record_count) AS avg_points_per_row
  FROM bird_tracking_10s
  WHERE time &amp;gt;= TIMESTAMP '2026-08-14T21:20:00Z'
    AND time " TIMESTAMP '2026-08-14T21:22:00Z'
)
SELECT
  raw_rows,
  birds,
  downsampled_rows,
  represented_raw_rows,
  avg_points_per_row,
  ROUND(
    100.0 * (
      1.0 - CAST(downsampled_rows AS DOUBLE) / CAST(raw_rows AS DOUBLE)
    ),
    1
  ) AS row_reduction_percent
FROM raw CROSS JOIN downsampled;&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id="example-output"&gt;Example Output&lt;/h4&gt;

&lt;p&gt;The equality between &lt;code class="language-markup"&gt;raw_rows&lt;/code&gt; and &lt;code class="language-markup"&gt;represented_raw_rows&lt;/code&gt; is an important completeness check. The 90% figure is a reduction in rows for this query shape, not a promise of an identical reduction in bytes on disk. Actual storage depends on schema, tags, fields, compression, and retention settings.&lt;/p&gt;

&lt;p&gt;You should also compare aggregates against the query-time SQL version before applying any raw-data retention policy.&lt;/p&gt;

&lt;h2 id="downsampling-best-practices-for-production"&gt;Downsampling best practices for production&lt;/h2&gt;

&lt;p&gt;The tutorial uses short intervals so you can see results quickly. A production workload might keep second-level raw data briefly, create 5-minute summaries for operational dashboards, and return hourly summaries for long-term reporting.&lt;/p&gt;

&lt;p&gt;When designing that pipeline:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-markup"&gt;window=2min&lt;/code&gt; gives each execution a lookback window large enough to reprocess recent data.&lt;/li&gt;
  &lt;li&gt;Start with the questions users need to answer, then choose the interval. A bin that is too wide can hide short-lived behavior.&lt;/li&gt;
  &lt;li&gt;Preserve the tags you need for filtering and grouping. Removing a dimension during aggregation cannot be reversed later.&lt;/li&gt;
  &lt;li&gt;Select aggregates that match the signal. Gauges often need average, minimum, and maximum; counters may need sums or rates.&lt;/li&gt;
  &lt;li&gt;Account for ingestion delay with &lt;code class="language-markup"&gt;offset&lt;/code&gt;, and use a lookback window that can catch expected late data.&lt;/li&gt;
  &lt;li&gt;Validate counts and values over multiple completed intervals before shortening raw-data retention.&lt;/li&gt;
  &lt;li&gt;Monitor the Processing Engine logs and query latency after deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="troubleshoot-a-scheduled-downsampler"&gt;Troubleshoot a scheduled downsampler&lt;/h2&gt;

&lt;p&gt;If the target table remains empty, inspect the Processing Engine logs:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code class="language-sql"&gt;SELECT
  trigger_name,
  log_level,
  log_text,
  event_time
FROM system.processing_engine_logs
ORDER BY event_time DESC
LIMIT 20;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then check the most common causes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The source table or a field name does not match the trigger arguments.&lt;/li&gt;
  &lt;li&gt;The source does not contain data within the plugin’s window and offset.&lt;/li&gt;
  &lt;li&gt;A Python dependency required by a plugin has not been installed.&lt;/li&gt;
  &lt;li&gt;The server cannot retrieve a remote &lt;code class="language-markup"&gt;gh:&lt;/code&gt; plugin.&lt;/li&gt;
  &lt;li&gt;The selected aggregate is not valid for a field’s data type.&lt;/li&gt;
  &lt;li&gt;The newest interval is incomplete because the offset is too small.&lt;/li&gt;
  &lt;li&gt;Getting started with downsampling with InfluxDB 3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;InfluxDB 3 makes it possible to use the same SQL aggregation logic at two stages of a workload: interactively at query time and operationally as a persisted rollup. Start with &lt;code class="language-markup"&gt;DATE_BIN&lt;/code&gt; to confirm the right interval and dimensions. When the query becomes a stable, repeated access pattern, schedule the official Python downsampler and include an offset so it works on completed data.&lt;/p&gt;

&lt;p&gt;Try the tutorial with &lt;a href="https://www.influxdata.com/influxdb-signup/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=downsampling_guide_influxdb_3&amp;amp;utm_content=blog"&gt;InfluxDB 3&lt;/a&gt; and the &lt;a href="https://github.com/influxdata/influxdb3_plugins/tree/main/influxdata/?utm_source=website&amp;amp;utm_medium=direct&amp;amp;utm_campaign=downsampling_guide_influxdb_3&amp;amp;utm_content=blog"&gt;official InfluxDB 3 plugin library&lt;/a&gt;. Once your results match the raw source over a completed interval, adapt the interval, aggregates, offset, and retention strategy to your production workload.&lt;/p&gt;

&lt;h2 id="faqs"&gt;FAQs&lt;/h2&gt;

&lt;div id="accordion_second"&gt;
    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-1"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;What is downsampling?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-1" class="message-body is-collapsible is-active" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Downsampling is the process of grouping time series points into wider time intervals and calculating summaries such as averages, minimums, maximums, sums, or counts. InfluxDB 3 can calculate those summaries at query time with SQL or persist them with a Python Processing Engine.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-2"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How do I downsample data with InfluxDB 3 SQL?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-2" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
              Use &lt;code class="language-markup"&gt;DATE_BIN&lt;/code&gt; to place timestamps into fixed intervals, apply aggregate functions such as &lt;code class="language-markup"&gt;AVG&lt;/code&gt; or &lt;code class="language-markup"&gt;MAX&lt;/code&gt;, and group by the binned time plus any tags you want to preserve. SQL downsampling returns aggregate rows but does not automatically write them to another table.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-3"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;When should I use the Python Processing Engine instead of SQL alone?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-3" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Use the Processing Engine when you want to precompute and store a rollup on a schedule. It is a good fit for aggregates used repeatedly by dashboards or long-range reports. Use query-time SQL when you need flexible intervals, are still exploring the data, or do not want another stored representation.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-4"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How do I prevent partial downsampling windows?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-4" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Set the downsampler plugin’s `offset` so it queries intervals that have finished receiving data. The offset should cover normal ingestion latency and expected late arrivals. Validate completeness by comparing the sum of `record_count` in the aggregate table with the raw row count over the same closed interval.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-5"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;Does downsampling delete the original data?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-5" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                No. Both a SQL aggregate query and the downsampler plugin leave the source data intact. The plugin writes additional rows to a target table. Raw-data deletion or expiration is controlled separately through retention settings.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-6"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;What does record_count mean in the downsampled table?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-6" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                `record_count` is the number of source records represented by an aggregate row. It is useful for detecting incomplete bins and for comparing the target table with the source over the same period.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-7"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;Can I calculate more than one aggregate per interval?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-7" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                Yes. A SQL query can return multiple functions such as AVG(speed), MIN(speed), and MAX(speed) in the same group. The official downsampler accepts calculation mappings for multiple fields. Choose only the summaries your queries need to avoid unnecessary write and storage overhead.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-8"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;Does this approach work with InfluxDB 3 Cloud Serverless or Cloud Dedicated?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-8" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                The embedded Python Processing Engine workflow in this tutorial applies to InfluxDB 3 Core and Enterprise. For InfluxDB Cloud Serverless, follow the documented client-library downsampling pattern: query aggregates with SQL, write the results back, and schedule the client externally. For Cloud Dedicated, you can use the same general query-and-write pattern with an InfluxDB 3 client library and an external scheduler. 
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

    &lt;article class="message"&gt;
        &lt;a href="javascript:void(0)" data-action="collapse" data-target="collapsible-message-accordion-second-9"&gt;
            &lt;div class="message-header"&gt;
                &lt;h3&gt;How much storage will downsampling save?&lt;/h3&gt;
                &lt;span class="icon"&gt;
                    &lt;i class="fas fa-angle-down" aria-hidden="true"&gt;&lt;/i&gt;
                &lt;/span&gt;
            &lt;/div&gt;&lt;/a&gt;
        &lt;div id="collapsible-message-accordion-second-9" class="message-body is-collapsible" data-parent="accordion_second" data-allow-multiple="true"&gt;
            &lt;div class="message-body-content"&gt;
                There is no universal percentage. The tutorial reduced the number of rows returned for its fixed test window by 90%, but byte-level storage depends on the schema, data types, tag cardinality, compression, the aggregates stored, and how long you retain each resolution.
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;

&lt;/div&gt;
</description>
      <pubDate>Wed, 19 Aug 2026 08:00:00 +0000</pubDate>
      <link>https://www.influxdata.com/blog/downsampling-guide-influxdb-3/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/downsampling-guide-influxdb-3/</guid>
      <category>Developer</category>
      <author>Charles Mahler (InfluxData)</author>
    </item>
  </channel>
</rss>
