Use Prometheus alert rule templates for stable, label based alerts. Use Grafana alerting templates when your team wants richer messages, contact routing, and a friendlier UI. Prometheus is better for the alert logic itself. Grafana is better for packaging that alert for humans who are half awake at 03:00.
TLDR: Prometheus placeholder variables are simple and reliable, like {{ $labels.instance }} and {{ $value }}. Grafana alerting gives you more message options, but dashboard variables such as $server usually do not work the way people expect in alert rules. In a team with 40 services, Prometheus rules may cut noisy alert edits by 30% because labels do the repeat work. Example: one alert can cover 200 pods if it uses {{ $labels.pod }} instead of hardcoded pod names.
What are placeholder variables?
Placeholder variables are little name tags inside alert text.
They get replaced when the alert fires.
Think of them as blanks in a tiny emergency postcard.
- Server:
{{ $labels.instance }} - Job:
{{ $labels.job }} - Value:
{{ $value }}
When an alert fires, Prometheus fills those blanks.
So this:
summary: "High CPU on {{ $labels.instance }}"
description: "CPU is at {{ $value }} for job {{ $labels.job }}"
May become this:
summary: "High CPU on api-07"
description: "CPU is at 91.4 for job checkout-api"
Nice. Simple. No drama.
The Prometheus way
Prometheus alerting rules live in YAML files.
That sounds boring.
It is also why they work so well.
A common Prometheus alert looks like this:
groups:
- name: api.rules
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 10m
labels:
severity: warning
team: payments
annotations:
summary: "High errors on {{ $labels.instance }}"
description: "Error rate is {{ $value }} for {{ $labels.job }}"
The most used placeholders are:
{{ $labels.label_name }}for metric labels.{{ $value }}for the alert value.{{ $externalLabels.label_name }}for labels set on the Prometheus server.
This makes Prometheus great for multi-instance alerts.
One rule can alert on many targets.
You do not need one rule per server.
You do not need one rule per pod.
You do not need to cry into your keyboard every time Kubernetes creates a new name like cart-service-7f9cbd99-k2pqx.
Where Prometheus placeholders shine
Prometheus is best when alerts are driven by labels.
Labels are the heart of Prometheus anyway.
Use them in alert text.
Use them in routing.
Use them in grouping.
For example:
summary: "{{ $labels.service }} is down"
description: "{{ $labels.instance }} has been unreachable for 5 minutes."
This is clean.
It tells the responder what broke.
It avoids copy pasted alert rules.
It also keeps Git history sane.
If you run 100 services, this matters a lot.
The annoying part
Prometheus templates are not a full app builder.
They are small on purpose.
Honestly, it feels like Prometheus says, “Here are labels and values. Please do not get fancy.”
That is usually a good thing.
But it can feel cramped when you want smart message formatting, rich links, team specific wording, or pretty summaries.
You can use Go template functions in some places, but the setup is not as friendly as clicking around in a UI.
Expect to waste time on tiny template mistakes.
A missing brace can steal 10 minutes from your life.
The Grafana alerting way
Grafana alerting feels more visual.
You create alert rules in the UI.
You can query Prometheus, Loki, Mimir, Graphite, and more.
Then you shape the alert and notification.
Grafana has its own template data.
In notification templates, you may see items like:
{{ .Labels }}{{ .Annotations }}{{ .Values }}{{ .Status }}{{ .StartsAt }}{{ .GeneratorURL }}
Grafana can send better looking messages to Slack, Teams, email, PagerDuty, and webhooks.
That is the charm.
It is often nicer for people who do not want to edit YAML.
The big Grafana trap: dashboard variables
This one bites many teams.
Grafana dashboard variables and Grafana alert rule templates are not the same thing.
Your dashboard may use $cluster, $namespace, or $app.
That does not mean your alert rule can use them like a dashboard panel.
It drives me crazy that an alert can look “almost right” in the UI, then fail because a dashboard variable was treated like fairy dust.
Grafana alerting is not meant to run one alert rule per dashboard dropdown choice.
Instead, write the query so labels split the results.
Let the alert become multi-dimensional.
For example, avoid thinking like this:
Alert for selected $namespace
Think like this:
sum by (namespace, pod) (
rate(container_cpu_usage_seconds_total[5m])
) > 0.8
Now each namespace and pod can become its own alert instance.
No dropdown magic needed.
Prometheus vs Grafana placeholders
Here is the simple split.
| Feature | Prometheus rules | Grafana alerting |
|---|---|---|
| Main use | Define alert logic close to metrics. | Create and manage alerts in a UI. |
| Common placeholders | {{ $labels.instance }}, {{ $value }} |
{{ .Labels }}, {{ .Values }}, {{ .Annotations }} |
| Best for | Reliable label based alerting. | Richer notifications and mixed data sources. |
| Weak spot | Less friendly formatting. | Dashboard variables can mislead users. |
Best practice: keep logic boring
Boring alert logic is good alert logic.
Put the hard truth in the query.
Put the helpful words in the annotations.
Do not hide too much cleverness inside templates.
A good Prometheus alert says:
- What broke?
- Where did it break?
- How bad is it?
- Who owns it?
- What should I click next?
Example:
annotations:
summary: "{{ $labels.service }} has high latency"
description: "P95 latency is {{ $value }} seconds in {{ $labels.namespace }}."
runbook: "https://wiki.example.com/runbooks/high-latency"
That is useful at 03:00.
That is the real test.
Image not found in postmetaWhen to choose Prometheus
Choose Prometheus rules when you want alerts as code.
Choose it when Git review matters.
Choose it when many services share the same rule pattern.
Choose it when labels already carry ownership data like team, service, and environment.
Prometheus is also a strong pick for Kubernetes.
Pods come and go.
Labels stay useful.
The rule does not need edits every time the cluster sneezes.
When to choose Grafana
Choose Grafana alerting when your team needs a friendlier control panel.
Choose it when alerts use several data sources.
Choose it when notification templates need more polish.
Grafana is great for teams who want fast edits without opening a pull request.
That can be good.
It can also be risky.
Someone may “fix” an alert in the UI and forget to tell anyone.
Use folders, permissions, and provisioning if you care about order.
A practical rule of thumb
Use Prometheus for the alert brain.
Use Grafana for the alert face.
If your alert depends on metric labels, Prometheus placeholders are enough.
If your alert message needs rich routing, nicer formatting, or several contact points, Grafana can help.
But do not build alerts around dashboard dropdown variables.
That road is full of tiny traps.
Build around labels instead.
Labels scale.
Hardcoded names rot.
And nobody wants to debug a broken placeholder while production is on fire.