x-pack/platform/plugins/shared/alerting_v2/server/README.md
This is the main architecture document for the alerting_v2 plugin. Read this file first if you want to understand the big picture before diving into one subsystem.
The goal of the plugin is simple:
If you already know the high-level flow and want subsystem detail, jump to:
| Concern | Document |
|---|---|
| Rule execution pipeline, middleware, streaming steps | lib/rule_executor/README.md |
| Episode lifecycle and transition strategies | lib/director/README.md |
| Notification matching, grouping, throttling, dispatch | lib/dispatcher/README.md |
| Data streams, mappings, and ES|QL views | resources/README.md |
The plugin is easiest to understand as five cooperating layers:
| Layer | What it owns | Main code |
|---|---|---|
| Control plane | User-facing APIs, saved objects, privileges, UI, startup wiring | public/, server/routes/, server/saved_objects/, server/setup/ |
| Evaluation plane | Running rules and turning query results into rule events | lib/rule_executor/ |
| Lifecycle plane | Turning alert rule events into episode state transitions | lib/director/ |
| Delivery plane | Turning episodes into notification work and recording outcomes | lib/dispatcher/ |
| Persistence plane | Data streams and ES|QL views used by the other layers | resources/ |
Those layers deliberately do different jobs:
A rule is a saved object that defines:
signal rule or an alert rulealert rulesRules are persisted under saved_objects/ and managed through routes/ plus lib/rules_client/.
A rule event is the immutable output document for one evaluated row or derived outcome from one rule run. Rule events are written to .rule-events and never updated in place.
Each event has:
type: signal or alertstatus: breached, recovered, or no_datagroup_hash: the series identifier inside that ruledata: the flattened ES|QL row payloadepisode.* fields for persisted alert-type rulessignal events stop here. Persisted alert events continue into lifecycle and notification processing and are expected to carry episode.* after DirectorStep enriches them.
A series is the per-rule stream of events sharing the same group_hash. It is the stable identity used to compare runs, detect recoveries, scope suppressions, and correlate lifecycle state over time.
An episode is the lifecycle container for an alert series. Episodes exist only for type: alert events.
episode.id, episode.status, and episode.status_count.Episode statuses are:
| Status | Meaning |
|---|---|
inactive | The series is not currently active. |
pending | The series breached but has not yet met activation criteria. |
active | The series is actively alerting. |
recovering | The series stopped breaching but has not yet fully returned to inactive. |
A notification policy is a saved object that is evaluated by the dispatcher, not embedded in the rule. Policies define:
One policy can match episodes from many rules in the same space.
An alert action is an append-only document in .alert-actions describing something that happened to an alert or notification group, for example:
ack, snooze, activate, deactivateThis stream is the dispatcher's durable memory.
The whole plugin revolves around two append-only streams:
.rule-events: what rule execution produced.alert-actions: what users and the dispatcher did with those eventspublic/ lets users manage rules, alerts/episodes, and notification policies.server/routes/ expose the same capabilities on the server..rule-events.group_hash..rule-events..alert-actions..alert-actions..rule-events for recovery and lifecycle state..alert-actions for suppression and throttling semantics. ┌──────────────────────────────┐
│ Management UI / APIs │
│ public/ + routes/ + clients │
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ Saved objects + services │
│ rules / notification │
│ policies / privileges │
└──────────────┬───────────────┘
│
┌────────────────────┴────────────────────┐
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ Rule executor task │ │ Dispatcher task │
│ one task per enabled │ │ fixed interval │
│ rule │ │ │
└─────────────┬────────────┘ └─────────────┬────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ Rule executor pipeline │ │ Dispatcher pipeline │
│ ES|QL -> rule events │ │ episodes -> groups -> │
│ -> director -> store │ │ dispatch -> action log │
└─────────────┬────────────┘ └─────────────┬────────────┘
│ │
▼ ▼
`.rule-events` `.alert-actions`
▲ ▲
└─────────────── reads and writes ────────┘
These boundaries keep the architecture understandable. If a change crosses one of them, that is a signal to slow down and verify the design.
.rule-events.alert-actionsThe plugin uses Inversify-based dependency injection and startup hooks:
| Path | Role |
|---|---|
server/index.ts | Registers setup/start hooks, services, tasks, and subsystem bindings. |
setup/bind_on_setup.ts | Registers privileges, saved objects, UI settings, telemetry setup, and task definitions. |
setup/bind_on_start.ts | Initializes Elasticsearch resources and schedules background tasks. |
setup/bind_routes.ts | Registers HTTP routes. |
setup/bind_services.ts | Binds shared services, clients, dispatcher enablement, and director strategies. |
setup/bind_rule_executor.ts | Registers rule executor middleware and steps in execution order. |
setup/bind_dispatcher_executor.ts | Registers dispatcher steps in execution order. |
setup/bind_tasks.ts | Registers Task Manager definitions for rule execution, dispatcher, and support tasks. |
| Path | Role |
|---|---|
public/ | UI applications, hooks, API wrappers, and app mounting. |
lib/rule_executor/ | Per-rule execution pipeline. |
lib/director/ | Alert episode state engine. |
lib/dispatcher/ | Notification pipeline. |
lib/services/ | Shared ES, storage, logging, retry, user, and saved object services. |
resources/ | Datastreams and ES|QL views. |
routes/ | HTTP API surface. |
saved_objects/ | Rule and notification policy persistence models. |
If your change is about...
lib/rule_executor/README.mdlib/director/README.mdlib/dispatcher/README.mdresources/README.mdroutes/, saved_objects/, and the relevant subsystem togetherpublic/ and confirm whether server route or saved object changes are needed tootypes.ts, update the step bindings, and add tests at the step and pipeline level.