# How Telegraf State Persistence Works Across Restarts

> Learn how Telegraf state persistence works across restarts. Telegraf uses the Stateful interface and gob-encoded files to save and load plugin state, ensuring data integrity after agent restarts.

- Repository: [InfluxData/telegraf](https://github.com/influxdata/telegraf)
- Tags: internals
- Published: 2026-05-14

---

**Telegraf persists plugin state across restarts through the `Stateful` interface, where plugins implement `GetState()` to return data and `SetState()` to receive encoded state bytes, with the agent managing atomic save/load operations via gob-encoded files in `~/.telegraf/`.**

Telegraf, the open-source server agent for collecting and reporting metrics, implements state persistence to ensure critical plugin data survives process restarts. This mechanism allows processors and inputs to maintain continuity for deduplication caches, script variables, and other runtime data across deployment cycles. Understanding how state persistence works in the `influxdata/telegraf` repository helps operators build resilient monitoring pipelines that retain context through maintenance windows and unexpected interruptions.

## The Stateful Interface Contract

State-aware plugins implement the **`Stateful`** interface defined in [`plugins/state.go`](https://github.com/influxdata/telegraf/blob/main/plugins/state.go). This contract requires two methods that separate data serialization concerns from the plugin's business logic.

- **`GetState() interface{}`** – Called during shutdown to retrieve the data structure that must survive the restart. The plugin returns its internal state (typically a map or struct) without worrying about encoding.

- **`SetState(state interface{}) error`** – Invoked at startup with the previously saved payload. The agent passes the raw bytes to the plugin, which decodes and hydrates its internal structures.

```go
// plugins/state.go
type Stateful interface {
    GetState() interface{}
    SetState(state interface{}) error
}

```

## State Persistence Lifecycle

The core agent in [`agent/agent.go`](https://github.com/influxdata/telegraf/blob/main/agent/agent.go) orchestrates the save and restore operations around the plugin execution lifecycle.

### Startup State Restoration

When Telegraf initializes, it scans configured plugins for `Stateful` implementations. For each match, the agent constructs a filename following the pattern `<plugin-type>_<plugin-name>.state` (for example, `processor_dedup.state`) and searches the state directory.

- **Default location**: `~/.telegraf/`
- **Custom location**: Override with the `--state-dir` flag
- **Encoding**: `encoding/gob`

If the file exists, the agent decodes the gob-encoded bytes and passes the `[]byte` payload to the plugin's `SetState` method.

### Runtime Operation

Once restored, the plugin operates normally using its hydrated cache. The deduplication processor, implemented in [`plugins/processors/dedup/dedup.go`](https://github.com/influxdata/telegraf/blob/main/plugins/processors/dedup/dedup.go), uses this restored map to identify metrics it has already emitted, preventing duplicates immediately upon restart without requiring a warmup period.

### Shutdown State Capture

Upon receiving a termination signal, the agent iterates through all `Stateful` plugins and calls `GetState`. The returned interface undergoes gob encoding, and the agent performs an **atomic write** to prevent corruption:

1. Write encoded bytes to a temporary file
2. Rename the temporary file to the target state filename

This ensures that a crash during write never leaves a partially written state file.

## Implementation Examples in Production Plugins

The Telegraf codebase includes several reference implementations demonstrating state persistence patterns.

### Dedup Processor

Located in [`plugins/processors/dedup/dedup.go`](https://github.com/influxdata/telegraf/blob/main/plugins/processors/dedup/dedup.go), this processor maintains a map of metric hashes to suppress duplicate outputs. The state file preserves this cache across restarts, ensuring that metrics processed just before shutdown are not re-emitted as duplicates after startup.

```toml
[[processors.dedup]]
  # Automatically persists internal cache to disk

```

### Starlark Processor

The [`plugins/processors/starlark/starlark.go`](https://github.com/influxdata/telegraf/blob/main/plugins/processors/starlark/starlark.go) implementation exposes a user-defined dictionary named `state` that persists between runs. When the Telegraf process restarts, user scripts regain access to variables set during previous executions, enabling cumulative calculations and counters that survive reboots.

## Configuring Storage Locations and Security

State persistence respects the `--state-dir` command-line flag, allowing operators to relocate files to dedicated volumes or tmpfs mounts. Files follow strict naming conventions (`<type>_<name>.state`) and leverage atomic rename operations to guarantee durability.

- **Default path**: `~/.telegraf/processor_dedup.state`
- **Override**: `telegraf --state-dir=/var/lib/telegraf/state`
- **Permissions**: Files inherit standard OS permissions; no encryption is performed by default

## Summary

- Plugins implement the `Stateful` interface in [`plugins/state.go`](https://github.com/influxdata/telegraf/blob/main/plugins/state.go) with `GetState()` and `SetState()` methods.
- State files are stored in `~/.telegraf/` by default, or a custom path specified by `--state-dir`.
- Data is encoded using Go's `encoding/gob` and written atomically to prevent corruption.
- The agent in [`agent/agent.go`](https://github.com/influxdata/telegraf/blob/main/agent/agent.go) triggers saves on shutdown and restores on startup.
- Production examples include the dedup processor and Starlark processor.

## Frequently Asked Questions

### Where does Telegraf store plugin state by default?

Telegraf writes state files to `~/.telegraf/` using the naming convention `<plugin-type>_<plugin-name>.state`. You can redirect this to a custom directory using the `--state-dir` command-line flag when launching the agent.

### Which plugins support state persistence?

Any plugin implementing the `Stateful` interface supports persistence. Notable examples include the **dedup** processor ([`plugins/processors/dedup/dedup.go`](https://github.com/influxdata/telegraf/blob/main/plugins/processors/dedup/dedup.go)) for duplicate suppression caches and the **starlark** processor ([`plugins/processors/starlark/starlark.go`](https://github.com/influxdata/telegraf/blob/main/plugins/processors/starlark/starlark.go)) for user-defined persistent variables.

### How is state data encoded and secured?

State data is serialized using Go's `encoding/gob` format for efficient binary storage. Writes are performed atomically (temporary file plus rename) to prevent corruption during crashes. Telegraf does not encrypt state files by default; filesystem-level encryption should be used for sensitive data.

### Can I disable state persistence for specific plugins?

No granular per-plugin disable flag exists; however, state is only persisted for plugins that explicitly implement the `Stateful` interface. Removing the state file before startup effectively clears the plugin's memory, as `SetState` will receive no data and the plugin initializes with empty defaults.