Self-hosted service
influxdata/kapacitor avatar
influxdata/kapacitor

Kapacitor: alerts as TICKscript pipelines over time series

Open source framework for processing, monitoring, and alerting on time series data

2,376 stars478 forksGoMIT

At a glance

What is it?
A Go server from the InfluxData family that runs small scripts against streaming and batch data, evaluates thresholds in those scripts, and ships alerts to Slack, VictorOps, PagerDuty or anywhere else a handler exists.
Who is it for?
Kapacitor earns its place when the alert logic is the hard part rather than the delivery. If your rule set is a handful of thresholds, InfluxDB alerts or a Prometheus rule file covers it and you avoid another service.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two binaries, and one that prints its own config

Kapacitor describes itself as an open source framework for processing, monitoring and alerting on time series data, and it ships as two separate programs. `kapacitor` is a command line client that talks to the API. `capacitord` is the server daemon that does the work. Splitting them means you can run the CLI on your laptop and the daemon on a server, with only HTTP between them.

Installing from source is two `go get` calls, one per binary:

sh
go get github.com/influxdata/kapacitor/cmd/kapacitor
go get github.com/influxdata/kapacitor/cmd/kapacitord

Binaries are also offered from a downloads page, and the README carries a Docker Hub badge for the official image, so there is a container path as well as a source path.

Configuration is where a new operator usually hesitates, because alerting tools tend to need a config file before they will start. Kapacitor answers that with a command that writes an example for you:

sh
kapacitord config

The repository keeps the reference version at `etc/kapacitor/kapacitor.conf`, which is the file to read when you want to know every available option rather than the handful you need to change. The config format is TOML, parsed by the BurntSushi TOML package that `go.mod` pins.

TICKscript is a pipeline, and the pipe character is literal

Tasks are defined in a domain specific language the project calls TICKscript, and the syntax is the closest thing in the time series world to a shell pipeline. A task starts with a source, either `stream` for streaming data or `batch` for range queries, then passes through nodes connected with a literal `|` character. The visual resemblance to a Unix pipeline is exact, down to the indentation style of the examples.

The README's CPU example is worth reading closely because it exercises most of the shape in thirty lines. It selects a measurement and groups by host, opens a window, takes a mean, then uses `eval` to invert the idle percentage into a used percentage:

javascript
stream
    |from()
        .measurement('cpu_usage_idle')
        .groupBy('host')
    |window()
        .period(1m)
        .every(1m)
    |mean('value')
    |eval(lambda: 100.0 - "mean")
        .as('used')
    |alert()
        .message('{{ .Level}}: {{ .Name }}/{{ index .Tags "host" }} has high cpu usage: {{ index .Fields "used" }}')
        .warn(lambda: "used" > 70.0)
        .crit(lambda: "used" > 85.0)

        // Send alert to hander of choice.

        // Slack
        .slack()
        .channel('#alerts')

        // VictorOps
        .victorOps()
        .routingKey('team_rocket')

        // PagerDuty
        .pagerDuty()

Three things are worth pulling out of that example. The window has both a `period` and an `every`, which is how you say the window is one minute wide and advances every minute, the standard tumbling window. The `eval` lambda does arithmetic on a named field, which is the mechanism that keeps thresholds readable: you compute `used` once and then compare against it twice rather than inverting the comparison at each threshold. And the alert handlers chain directly off the end, so adding PagerDuty is one method call rather than a second rule to keep in sync with the first.

The `{{ .Name }}` and `{{ index .Tags "host" }}` syntax is Go template interpolation, not a Kapacitor invention, which means message formatting is as expressive as Go templates and as finicky as they are.

Define and enable are separate steps, and that is deliberate

A script file on disk is not a running alert. You register the script with the server, which the project calls defining the task, and then you enable it. The split matters in practice, because it gives you a review point: a task can exist in a disabled state while you check its definition, and an alert that fires wrongly can be turned off without deleting the script that produced it.

The command sequence from the README:

sh
# Define the task (assumes cpu data is in db 'telegraf')
kapacitor define \
    cpu_alert \
    -type stream \
    -dbrp telegraf.default \
    -tick ./cpu_alert.tick
# Start the task
kapacitor enable cpu_alert

The flags carry most of the meaning. The task name is `cpu_alert`, and it becomes the identifier you pass to every later command. The `-type` flag is what tells the server whether the script begins with `stream` or `batch`. The `-dbrp` flag is a database and retention policy pair, written as a dotted string, and it is the piece most likely to trip you up: it names where the data is read from, not where alerts go.

The script itself is passed by path, so the file can live in version control next to the code that depends on the alert. That combination, a committed TICKscript plus a name you can enable and disable, is the pattern the tooling is built around. The repository ships example scripts under `examples/telegraf`, plus `examples/nodes` for per node examples and `examples/scores` for scoring behaviour, so you can read working scripts before writing your own.

A flat root of node files tells you the whole architecture

The repository tree is unusually legible. Rather than burying the processing engine in nested internal packages, the root directory holds one Go file per node type, and the filenames read as a list of operations: `alert.go`, `autoscale.go`, `barrier.go`, `batch.go`, `change_detect.go`, `combine.go`, `derivative.go`, `edge.go`, `eval.go`, `expr.go`, `flatten.go`, `group_by.go`, `http_out.go`, `http_post.go` and `influxdb_out.go`.

That layout is the architecture stated plainly. A task is a graph of nodes connected by edges, `edge.go` and the `edge/` directory hold the connection machinery, and each transform is a node type that consumes points and emits points. `barrier.go`, `combine.go` and `flatten.go` are the joins and reshapes, which are exactly the operations that a threshold rule cannot express and that make a separate processing layer worth having.

The generated file is worth noticing too: `influxql.gen.go` sits next to `influxql.gen.go.tmpl`, which means the InfluxQL query surface is produced from a template rather than written by hand. If you change the template you regenerate rather than edit. The `influxdb/`, `http/` and `client/` directories handle the edges in and out, and `cmd/` holds the two entry points that produced the CLI and the daemon.

Two design documents sit at the root, `DESIGN.md` and `BLOB_STORE_DESIGN.md`, alongside `CONTRIBUTING.md` and `SECURITY.md`. The build is not a single Makefile; there is `build.sh`, `build.py`, `generate.sh`, `gobuild.sh`, `checkfmt.sh` and `circle-test.sh`, which is the signature of a project that started with several build paths and kept them.

The dependency list explains what it can connect to

The single file in this snapshot, `go.mod`, declares Go 1.26.5 and a require block that doubles as a capability list. The InfluxData entries are the family members: `influxdb` at v1.9.6 for the 1.x line, `influxdb/v2`, `influxql` for query parsing, `flux` at v0.191.0 for the newer query language, plus `cron`, `pkg-config`, `wlog` and `usage-client`.

The two InfluxDB entries point in different directions and it is worth noticing what that means. The v1 entry is a released version, while the v2 entry is a pseudo version pinned to an alpha from April 2021. In other words, the 2.x support in this snapshot is not tracking the current 2.x releases. If your InfluxDB deployment is on 2.x and you rely on Kapacitor's InfluxDB output, check what that dependency actually resolves to before designing around it.

Beyond InfluxData, the interesting entries are the integration surface: `aws-sdk-go` for cloud destinations, `IBM/sarama` for Kafka and `eclipse/paho.mqtt.golang` for MQTT, `prometheus/client_golang` for exposing Kapacitor's own metrics, `gorhill/cronexpr` for cron style schedules, `benbjohnson/btree` and `cespare/xxhash` for the ordered and hashed lookup structures a data path needs, `mailru/easyjson` and `evanphx/json-patch` for serialization, `k-sone/snmpgo` for SNMP, and `opentracing-go` for distributed tracing.

The release history matches that dependency surface. v1.8.5 in May 2026 and v1.8.6 a few weeks later were Go version bumps, an `aws-sdk-go-v2` and `smithy-go` upgrade, and a gRPC upgrade. v1.8.7 in September 2026 moved to Go 1.26.5. Three releases, all maintenance, no feature announcements, which tells you the project is being kept current against its dependency tree rather than expanded. The 2,376 stars and 478 forks suggest a settled user base, while 833 open issues is a high ratio for a project of that size and worth weighing if you plan to file anything.

Editorial conclusion

Kapacitor earns its place when the alert logic is the hard part rather than the delivery. If your rule set is a handful of thresholds, InfluxDB alerts or a Prometheus rule file covers it and you avoid another service. If the rule set involves joining, resampling or evaluating per group, the scriptable pipeline model is what you are actually buying, and the README example is small enough to understand in one read before you commit to anything.

Two things to weigh. First, the root of the repository is a flat wall of single node files, which tells you the architecture plainly: a task is a chain of nodes, and each node type lives in its own file. That is a design you can learn, but it is also a surface where unfamiliar node names are hard to discover without leaving the repository. Second, the recent release history is almost entirely dependency work. Three of the last three releases named Go version bumps and library upgrades, so the project is being kept current rather than gaining features. The MIT license and a September 2026 commit date mean you can read the whole thing and decide for yourself.

Frequently asked questions

What is Kapacitor used for?

Kapacitor is described as an open source framework for processing, monitoring and alerting on time series data. Its distinguishing feature is that the processing and the alert logic live in one small script, written in TICKscript, rather than being split across a query tool and a separate alerting configuration. That lets a rule compute derived values, group by tag, join or reshape points, and only then compare against a threshold.

What is the difference between kapacitor and capacitord?

The repository ships two binaries. `kapacitor` is a CLI program for calling the Kapacitor API, and `capacitord` is the server daemon. Separating them means the client can run on your workstation while the daemon runs on a server, communicating over HTTP. Both are installed with a `go get` against `github.com/influxdata/kapacitor/cmd/`.

How do I install Kapacitor?

The README names three routes. From source, run `go get github.com/influxdata/kapacitor/cmd/kapacitor` and `go get github.com/influxdata/kapacitor/cmd/kapacitord`. There is also a downloads page for prebuilt binaries, and the repository carries a Docker Hub badge pointing at the official `kapacitor` image.

What is TICKscript and how does it define an alert?

TICKscript is the DSL Kapacitor uses to define tasks. A script begins with `stream` or `batch`, then chains nodes with a literal `|` character in the style of a shell pipeline. Thresholds live inside the `alert()` node as `.warn(...)` and `.crit(...)` lambda expressions, and message text uses Go template interpolation. Handlers such as `.slack()`, `.victorOps()` and `.pagerDuty()` chain directly off the alert node.

Is Kapacitor actively developed?

The recent releases are maintenance rather than feature work, and it is more accurate to describe the cadence that way. v1.8.5 and v1.8.6 in May 2026 were Go version bumps plus upgrades to `aws-sdk-go-v2`, `smithy-go` and gRPC, and v1.8.7 in September 2026 moved to Go 1.26.5. The most recent commit date in this snapshot is September 2026, and the license is MIT.

Official sources

  1. influxdata/kapacitor on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/influxdata-kapacitor.svg)](https://hysenlabs.com/projects/influxdata-kapacitor)