SynfraCore
Synfracore
Start Learning
Navigation

Academies

Platform

RoadmapsLabsCertificationsInterviewPYQsAI AssistantCareer
Start Learning Free🗺️ Learning Roadmaps

PrometheusTroubleshooting

Debug common issues with root cause analysis

✍️
Written by senior engineers. Reviewed for technical accuracy.· Updated 2025 · SynfraCore Prometheus Team
Expert Content

Prometheus Troubleshooting Guide

Issue 1: Target shows as DOWN in Prometheus UI

Symptom: In Prometheus → Status → Targets, a target shows state=DOWN with error message.

Root Cause: Target not reachable, wrong port, TLS mismatch, or target not exposing metrics endpoint.

Debug steps:

bash
# Test scrape endpoint manually
curl http://<target-ip>:<port>/metrics | head -20

# Check DNS resolution from Prometheus pod
kubectl exec -it prometheus-pod -n monitoring --   curl http://<service-name>.<namespace>.svc.cluster.local:8080/metrics

# Check Prometheus targets page
# http://<prometheus-url>/targets?search=myservice

Fix:

yaml
# Check scrape config in prometheus.yaml
scrape_configs:
  - job_name: 'myapp'
    static_configs:
      - targets: ['myapp:8080']   # correct port?
    metrics_path: '/metrics'       # correct path?
    scheme: 'http'                 # http vs https?

# For K8s, check ServiceMonitor
kubectl describe servicemonitor myapp -n monitoring
kubectl get endpoints myapp -n production  # are endpoints correct?

---

Issue 2: PromQL query returns no data

Symptom: Query in Grafana or Prometheus UI returns empty graph or "No data".

Root Cause: Wrong metric name, wrong label selectors, or time range issue.

Debug steps:

promql
# Start broad, then narrow
# Step 1: Check if metric exists at all
{__name__=~"http.*"}   # list all HTTP metrics
http_requests_total    # try without any labels

# Step 2: Check label values
http_requests_total{job="myapp"}  # check what label values exist
bash
# List all metrics from a target
curl http://prometheus:9090/api/v1/label/__name__/values | jq '.data | .[]' | grep http

# Check label values for a metric
curl 'http://prometheus:9090/api/v1/label/job/values'

Fix:

promql
# Wrong: assumes specific label that doesn't exist
rate(http_requests_total{status_code="200"}[5m])

# Right: check actual label names first, then use
rate(http_requests_total{code="200"}[5m])  # label is 'code' not 'status_code'

---

Issue 3: Prometheus out of memory / crashing

Symptom: Prometheus pod OOMKilled. kubectl logs prometheus-0 -n monitoring --previous shows killed.

Root Cause: Too many series (high cardinality), retention too long, or insufficient memory allocation.

Debug steps:

bash
# Check TSDB stats
curl http://prometheus:9090/api/v1/status/tsdb | jq '.data.headStats'

# Check cardinality issues
curl http://prometheus:9090/api/v1/status/tsdb | jq '.data.seriesCountByMetricName | sort_by(.seriesCount) | reverse | .[0:10]'

Fix:

yaml
# Reduce retention
args:
  - '--storage.tsdb.retention.time=15d'  # default is 15d, try 7d

# Increase memory
resources:
  requests:
    memory: "2Gi"
  limits:
    memory: "4Gi"

# Drop high-cardinality labels in scrape config
metric_relabel_configs:
  - source_labels: [user_id]
    action: drop  # remove per-user labels that cause cardinality explosion

---

Issue 4: Alert not firing despite condition being met

Symptom: Prometheus shows the alerting rule, but Alertmanager never receives it.

Debug steps:

bash
# Check alert state in Prometheus UI
# http://prometheus:9090/alerts

# Check Alertmanager received alerts
curl http://alertmanager:9093/api/v2/alerts

# Check Prometheus → Alertmanager connectivity
kubectl get pods -n monitoring | grep alertmanager
kubectl logs alertmanager-0 -n monitoring | grep error

# Verify alertmanager config
kubectl get secret alertmanager-main -n monitoring -o jsonpath='{.data.alertmanager\.yaml}' | base64 -d

Fix:

yaml
# Check alert rule syntax
groups:
  - name: example
    rules:
      - alert: HighErrorRate
        expr: rate(http_requests_total{code=~"5.."}[5m]) > 0.05
        for: 5m          # must be true for 5 minutes before firing
        labels:
          severity: critical
        annotations:
          summary: "High error rate on {{ $labels.job }}"

---

Issue 5: Grafana shows "No data" even though Prometheus has data

Symptom: Prometheus query returns data. Same query in Grafana shows empty panel.

Root Cause: Wrong data source URL, time zone mismatch, or variable interpolation issue.

Debug steps:

bash
# Test data source from Grafana
# Grafana UI → Configuration → Data Sources → Test

# Check Grafana logs
kubectl logs grafana-pod -n monitoring | grep -i error | tail -20

# Verify the query in Grafana → Explore mode
# Use same PromQL, check time range

Fix:

Set data source URL to: http://prometheus:9090 (internal cluster DNS, not external)
Check time zone: Grafana dashboard time zone must match browser/server
For template variables: use $__rate_interval instead of fixed [5m]
If the scrape interval is long relative to the query range, rate()/increase() need at least two samples inside the window to return anything — a [1m] range with a 2-minute scrape interval comes back empty. Fix it by widening the query range (e.g. [5m] instead of [1m]) or scraping more frequently — not by increasing the scrape interval further, which makes the gap worse.
Share:
Join our Community
Daily tips, job alerts, interview help — join engineers learning together
Up Next
🏆
PrometheusCertification
Exam guides, practice questions, and prep strategies
Also Worth Exploring
← Back to all Prometheus modules
Interview Q&ACertification