Grafana is a visualisation and dashboard platform. It does not collect or store your data — it queries other systems (Prometheus, Loki, PostgreSQL, Elasticsearch, InfluxDB and dozens more) and turns the results into graphs, tables and alerts.

What it is good at

  • Dashboards: Panels laid out on a grid, shared as code, embedded in other sites.
  • Ad-hoc exploration: Query a data source and see the result immediately without building a dashboard first.
  • Unified view: Metrics, logs and traces side by side, correlated by time and labels. This is the real strength — one place to look when something breaks.
  • Annotations: Mark deployments, incidents and maintenance windows on the timeline so you can see cause and effect.
  • Templating: Variables in the dashboard (server, environment, service) instead of hundreds of separate dashboards.

The dashboard you actually need

Start with four panels per service, based on the four golden signals:

1. Traffic      rate(requests_total[5m])            requests per second
2. Errors       5xx / total * 100                   error percentage
3. Latency      histogram_quantile(0.95, ...)       p95 response time
4. Saturation   cpu, memory, queue depth            how full is it

Additional, cheap and very useful:
5. Deployment annotations (releases marked on the timeline)
6. Instance availability: up{job="$service"}
7. Top-N slowest endpoints
8. Business metric (orders/min, signups/min)

Deliberately OUT of the top row: total requests since boot,
CPU per core, disk I/O detail. They belong lower down, if at all.

Variables instead of many dashboards

# A dashboard variable "instance" built from a query
label_values(up{job="node"}, instance)

# Then every panel uses it
rate(node_cpu_seconds_total{instance="$instance", mode="idle"}[5m])

# Extended: environment -> service -> instance, cascading
label_values(up, env)                              # env
label_values(up{env="$env"}, job)                  # job
label_values(up{env="$env", job="$job"}, instance) # instance

# Result: one dashboard serves every environment and service.
# Rule: never hard-code an instance or a hostname in a panel.

Alerting in Grafana vs Prometheus

  • Prometheus rules are the classic approach: rules live with the metrics, evaluated by Prometheus, routed by Alertmanager (grouping, silencing, inhibition, escalation).
  • Grafana alerting supports the same but works across any data source, including SQL. Useful when alerts depend on business data in a database.
  • Pragmatic choice: infrastructure alerts in Prometheus, business-logic alerts in Grafana. Do not duplicate the same alert in both systems — that guarantees double pages.

Dashboards as code

# Exporting a dashboard: the JSON is portable, but it is generated output.
# Keep the source in version control, not the exported JSON.

# Option A: provision dashboards from files
# /etc/grafana/provisioning/dashboards/default.yaml
apiVersion: 1
providers:
  - name: main
    type: file
    options:
      path: /var/lib/grafana/dashboards

# /etc/grafana/provisioning/datasources/prometheus.yaml
apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    jsonData:
      timeInterval: 15s

# Option B: generate dashboards with a tool so they can be reviewed in a PR
#   Grafonnet (Jsonnet) or Terraform's grafana provider
# That way "who changed which panel and why" is answerable from git history.

# Always verify provisioning took effect:
curl -s -u admin:geheim http://localhost:3000/api/search?query= | jq '.[].title'

Practical rules

  1. A dashboard must answer a question. "How is the API doing?" — not "here are 60 numbers". If nobody can say what a panel means, delete it.
  2. Top row = what a human should look at first during an incident.
  3. Use consistent colours and units. Green good, red bad, everywhere. Percentages as percent, not as fractions.
  4. Set a sensible default time range (last 6 hours, refresh 30 s). "Last 5 minutes" is too noisy for a first look.
  5. Annotate deployments. Half of all "the graph changed" investigations are answered by seeing that a release went out at exactly that time.
  6. Beware of averages. A 200 ms average can hide a very slow minority of users. Show percentiles (p95, p99).
  7. Screenshots in runbooks age badly. Link to the dashboard with a time range instead.
  8. Do not measure what nobody acts on. Every panel costs attention.

Permissions and access

# Grafana is not a security boundary - it holds read credentials
# for every data source. Treat it like a production system.
#   - Admin password not the default, and not "admin/admin"
#   - SSO / OIDC instead of local accounts
#   - Editor rights granted deliberately (an editor can query
#     any data source, which may include customer data)
#   - Anonymous access off
#   - Organisations/folders per team with minimum necessary access
#   - API keys / service accounts with short lifetimes for automation

# Typical mistake: exposing Grafana publicly "just for read".
# Read access to metrics often reveals internal topology,
# hostnames, traffic volumes and sometimes customer identifiers.

Related: Monitoring, Cache, Prometheus (DE), Monitoring mit Prometheus und Grafana (DE).