docs/sources/datasources/prometheus/annotations/index.md
Annotations overlay event data on your dashboard graphs, helping you correlate events with metrics. You can use Prometheus as a data source for annotations to display events such as deployments, alerts, or threshold crossings on your visualizations.
For general information about annotations, refer to Annotate visualizations.
Before creating Prometheus annotations, ensure you have:
To add a Prometheus annotation to your dashboard:
Prometheus annotations work differently from SQL-based annotations. Instead of querying a table of events, you write a PromQL expression that returns time-series data. Grafana converts the query results into annotation events using these rules:
> 0 or the ALERTS metric).{{< admonition type="note" >}}
Because every returned data point creates an annotation, queries that return continuous data (like node_cpu_seconds_total) will produce an annotation at every step interval, flooding your dashboard. Always use expressions that return data only at the moments you want annotated.
{{< /admonition >}}
After entering your PromQL expression, use the field mapping drop-downs to control how query results are displayed as annotations. Grafana shows mapping options for:
| Field | Description | Default behavior |
|---|---|---|
| Time | The timestamp for the annotation. | Uses the first time-type field (always present). |
| TimeEnd | An end timestamp for range annotations, which display as a shaded region instead of a vertical line. | Not set (produces point annotations). |
| Title | Short label displayed on the annotation marker. | Not set. |
| Text | The annotation description displayed when you hover over it. | Uses the first string-type field, or the metric/label display name if configured. |
| Tags | Comma-separated tags for the annotation. Helps categorize and filter annotations. | Not set. |
To configure field mappings, select the appropriate field name from each drop-down, or enter a fixed text value.
The following examples show common annotation patterns with Prometheus.
ALERTSThe most common and reliable way to create Prometheus annotations. Prometheus automatically generates an ALERTS metric for all configured alerting rules.
ALERTS{alertstate="firing"}
This creates an annotation at every step interval where an alert is firing. The ALERTS metric includes labels such as:
alertname — The name of the alerting rulealertstate — Either firing or pendingTo limit to specific alerts or severity levels:
ALERTS{alertname="HighCPUUsage", severity="critical"}
Configure the field mappings:
alertname (displays the alert name on hover)severity (allows filtering by severity)Display annotations when a process restarts. The changes() function detects when a value changes, and > 0 ensures annotations only appear at the moment of change:
changes(process_start_time_seconds{job="myservice"}[5m]) > 0
If you track deployments by pushing a timestamp metric via Pushgateway or a recording rule:
changes(deployment_timestamp_seconds{environment="production"}[10m]) > 0
Configure the field mappings:
environment (shows which environment was deployed)environmentDisplay annotations when available memory drops below 10%:
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 0.1
{{< admonition type="note" >}}
Comparison operators in PromQL act as filters — they only return data points where the condition is true. This means the expression above only returns data when memory is below 10%, and annotations only appear at those times. There's no need to add an outer > 0 wrapper.
{{< /admonition >}}
Display annotations when the number of running pods changes:
changes(kube_deployment_status_replicas{deployment="my-app"}[5m]) > 0
Display annotations when the error rate exceeds a threshold:
sum(rate(http_requests_total{status=~"5.."}[5m])) by (job) / sum(rate(http_requests_total[5m])) by (job) > 0.05
This creates annotations when the error rate exceeds 5%.
If you expose build metadata using a metric like build_info (common in Go services), annotate when the version changes:
changes(build_info{job="myservice"}[10m]) > 0
Configure the field mappings:
version (shows the new version in the annotation tooltip)jobIf your build info metric uses a version label (for example, build_info{version="1.2.3"}), the annotation tooltip displays the version that was deployed.
The Min step setting controls how many data points the query returns, which directly affects how many annotations appear. A larger step means fewer annotations:
1m — Up to one annotation per minute (good for short time ranges).5m — Up to one annotation per 5 minutes (good for day-range dashboards).1h — Up to one annotation per hour (good for week-range dashboards).If your dashboard shows too many annotation markers, increase the Min step or add more specific filters to your query.
You can use template variables in your annotation queries to filter annotations based on dashboard variable selections:
ALERTS{alertstate="firing", instance=~"$instance"}
changes(process_start_time_seconds{job="$job"}[5m]) > 0
Template variables in annotations are resolved at query time using the current dashboard variable values.
Range annotations display as shaded regions rather than vertical lines, representing events with duration. To create range annotations, the query result must include a TimeEnd field mapping.
Because PromQL doesn't natively return start/end time pairs, range annotations with Prometheus are limited to scenarios where you have separate metrics for start and end times (for example, via recording rules or custom metrics pushed to Pushgateway). For most use cases, point annotations (using the examples in this page) are the practical approach.
If your annotations aren't appearing or you encounter errors, refer to Troubleshoot Prometheus data source issues.