From zero visibility to production-grade observability.
This guide covers the principles, patterns, and pitfalls of building a monitoring
practice that actually works — not just dashboards that look pretty.
1. The Three Pillars of Observability
4. Alert Design: Avoiding Alert Fatigue
5. Dashboard Design Principles
http_requests_total, node_cpu_seconds_total2026-03-10T12:34:56Z ERROR failed to connect to database: timeoutRule of thumb: Use metrics to detect problems, logs to diagnose them, traces to understand service interactions.
SLIs are the metrics that matter — quantitative measures of your service's behavior from the user's perspective.
| SLI Type | What It Measures | Example Metric |
|---|---|---|
| Availability | % of successful requests | 1 - (5xx / total) |
| Latency | Response time distribution | p95 < 500ms |
| Throughput | Request processing rate | requests/sec |
| Error Rate | % of failed operations | errors / total * 100 |
| Freshness | Data age / staleness | time_since_last_update |
SLOs are targets for your SLIs. They define "good enough."
Example SLOs:
Availability: 99.9% (43.8 min downtime/month)
Latency p95: < 500ms
Latency p99: < 1000ms
Error rate: < 0.1%
Error Budget = 100% - SLO. If your SLO is 99.9%, you have a 0.1% error budget — that's ~43 minutes/month of allowed downtime.
SLAs are contracts with customers. They should always be less strict than your internal SLOs.
Internal SLO: 99.95% availability (you aim for this)
External SLA: 99.9% availability (you promise this)
Gap: 0.05% (your safety margin)
# Recording rule: SLI — success rate over 30 days
- record: sli:http_availability:ratio_rate30d
expr: |
1 - (
sum(rate(http_requests_total{status=~"5.."}[30d]))
/
sum(rate(http_requests_total[30d]))
)
# Alert: SLO burn rate (multi-window)
- alert: SLOBudgetBurnRateHigh
expr: |
(
sli:http_error_rate:ratio_rate1h > (14.4 * 0.001)
and
sli:http_error_rate:ratio_rate5m > (14.4 * 0.001)
)
for: 2m
labels:
severity: critical
annotations:
summary: "Error budget burn rate is 14.4x — budget exhaustion in ~1 hour"| Signal | Description | Prometheus Query |
|---|---|---|
| Rate | Requests per second | sum(rate(http_requests_total[5m])) |
| Errors | Failed requests per second | sum(rate(http_requests_total{status=~"5.."}[5m])) |
| Duration | Latency distribution | histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) |
Use RED for: APIs, web servers, microservices, gateways
| Signal | Description | Prometheus Query |
|---|---|---|
| Utilization | % of resource capacity in use | 1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) |
| Saturation | Queued work / backlog | node_load15 / count(node_cpu_seconds_total{mode="idle"}) |
| Errors | Error count/rate | rate(node_disk_io_time_weighted_seconds_total[5m]) |
Use USE for: CPU, memory, disk, network, connection pools
Most teams start with too many alerts. Within weeks, everyone ignores them. This is alert fatigue — the silent killer of incident response.
1. Alert on symptoms, not causes
BAD: CPU > 80% (cause — might not affect users)
GOOD: Error rate > 1% (symptom — users are affected)
GOOD: Latency p95 > 1s (symptom — users notice slowness)
2. Every alert must be actionable
If an engineer gets paged, they must be able to do something about it. If the response is "just wait," it shouldn't be an alert.
3. Use severity levels correctly
| Severity | Response | Examples |
|---|---|---|
| critical | Wake someone up (PagerDuty) | Service down, data loss, SLO breach |
| warning | Check next business day (Slack) | Disk filling up, elevated errors |
| info | Informational (Slack, low-priority) | Deployment complete, cert renewal |
4. Tune for durations to avoid flapping
# BAD: fires on every 1-second CPU spike
- alert: HighCPU
expr: cpu_usage > 90
for: 0s
# GOOD: only fires if sustained for 10 minutes
- alert: HighCPU
expr: cpu_usage > 90
for: 10m5. Use inhibition to reduce noise
When a host is completely down, you don't need 50 alerts — one "HostDown" alert is enough. AlertManager's inhibit_rules suppress downstream alerts.
Run a monthly alert review:
1. List all alerts that fired in the past month
2. For each: Was it actionable? Did someone respond? Was it a real problem?
3. Delete or tune alerts that fail these criteria
4. Add alerts for incidents that weren't caught
Every service should have a dashboard with these 4 panels:
1. Traffic — requests per second (tells you what's happening)
2. Errors — error rate / count (tells you what's broken)
3. Latency — p50, p95, p99 (tells you how slow it is)
4. Saturation — resource utilization (tells you how full it is)
┌─────────────────────────────────────────────────┐
│ Row 1: Key metrics (stat panels) │
│ [Request Rate] [Error %] [P95 Latency] [Avail] │
├─────────────────────────────────────────────────┤
│ Row 2: Traffic + Errors (time series) │
│ [Rate by status code] [Error rate by endpoint] │
├─────────────────────────────────────────────────┤
│ Row 3: Latency (time series) │
│ [Latency percentiles] [Latency by endpoint] │
├─────────────────────────────────────────────────┤
│ Row 4: Resources (time series) │
│ [CPU/Memory] [Connections] [Queue depth] │
└─────────────────────────────────────────────────┘
Every critical alert should have a runbook. Store these alongside your code.
# Runbook: [AlertName]
## Alert Description
What this alert means and why it matters.
## Impact
- Who is affected (users, internal, specific feature)
- Severity: critical / warning
## Investigation Steps
1. Check the dashboard: [link to Grafana dashboard]
2. Check recent deployments: `git log --oneline -10`
3. Check logs: Grafana → Explore → Loki → `{job="myapp"} |= "error"`
4. Check dependent services: [list]
## Common Causes
| Cause | How to Verify | Fix |
|-------|---------------|-----|
| Memory leak | RSS growing steadily | Restart pod, investigate leak |
| Database slow | Query duration > 5s | Check slow query log |
| Dependency down | Connection refused in logs | Check upstream service |
## Mitigation
1. Immediate: [what to do right now to reduce impact]
2. Short-term: [what to fix within hours]
3. Long-term: [what to fix to prevent recurrence]
## Escalation
- L1: On-call engineer (PagerDuty)
- L2: Team lead
- L3: Platform team
## References
- Architecture doc: [link]
- Previous incidents: [links to postmortems]Alert fires
│
├── Acknowledge (PagerDuty / Slack)
│
├── Assess severity (who is affected? how bad?)
│
├── Investigate (dashboards → logs → traces)
│
├── Mitigate (reduce impact now)
│ ├── Rollback deployment
│ ├── Scale up resources
│ ├── Enable circuit breaker
│ └── Redirect traffic
│
├── Fix (root cause)
│
├── Verify (confirm alert resolves, metrics normalize)
│
└── Postmortem (blameless, actionable)
├── What happened?
├── Timeline of events
├── What worked well?
├── What could be improved?
└── Action items (with owners and deadlines)
| Component | CPU | Memory | Disk (30d retention) |
|---|---|---|---|
| Prometheus | 0.5-2 cores | 2-8 GB | 10-50 GB |
| Grafana | 0.25-1 core | 256 MB-1 GB | 1 GB |
| AlertManager | 0.1 core | 128 MB | 100 MB |
| Loki | 0.5-2 cores | 1-4 GB | 10-100 GB |
| Promtail | 0.1-0.5 core | 128-512 MB | positions file only |
| node-exporter | 0.1 core | 64 MB | — |
| cAdvisor | 0.25 core | 128-512 MB | — |
| Metric | Threshold | Action |
|---|---|---|
| Active time series | > 1M | Consider Thanos/Cortex |
| Log ingestion | > 10 GB/day | Consider horizontal Loki |
| Prometheus memory | > 8 GB | Increase retention, use recording rules |
| Query latency | > 30s | Add recording rules, optimize queries |
Datanest Digital | datanest.dev | MIT License
Questions? Email support@datanest.dev
Complete observability stack with Prometheus, Grafana, Loki, and AlertManager.
One
docker compose upto full production monitoring. Stop flying blind.



Get the full Monitoring Stack Setup and unlock everything.
Get the complete guide with every chapter unlocked, including code samples, diagrams, and best practices.
Access all interactive tools with complete data, all workload profiles, and the full scenario library.
Downloadable source code, configuration files, and working examples from every chapter.
Free updates for life. Every new chapter, tool, and improvement included.