Prometheus and Grafana: Full Monitoring Stack

Khimananda Oli 7 min read Virtualization
Prometheus and Grafana: Full Monitoring Stack

By Khimananda Oli | Last reviewed: August 2026

Building a reliable Prometheus and Grafana: Full Monitoring Stack is the baseline requirement for operating modern cloud infrastructure, yet most deployments fail due to ephemeral storage or insecure defaults. You need more than just running containers; you need a system that survives restarts, enforces authentication, and provides genuine signal over noise. This guide covers the architectural decisions and configuration patterns required to move from a toy setup to an audit-ready observability platform suitable for production environments in Nepal and globally.

How does the Prometheus and Grafana full monitoring stack architecture work?

Understanding the data flow prevents costly re-architecture later. In this stack, Prometheus acts as the central time-series database (TSDB) that actively scrapes metrics endpoints via HTTP at defined intervals. It does not receive pushed data by default; it pulls. This pull model simplifies network configuration and makes target health checking intrinsic to the collection process. Grafana sits purely as a visualization layer, querying Prometheus via PromQL without storing any metric data itself. For a deeper understanding of how these components fit into broader observability, see our guide on observability vs monitoring logs metrics and traces.

Node Exporter:9100/metricsApp Metrics:8080/metricsPrometheusTSDB + ScraperPull Model (HTTP)GrafanaVisualizationAlertmanagerDedup & Route
Architecture diagram of the Prometheus and Grafana full monitoring stack illustrating the pull-based scraping model and component separation.

The critical distinction in this architecture is statefulness. Prometheus maintains a local TSDB on disk. If you deploy it without persistent storage, every pod restart wipes your historical data and resets alert states. Grafana, conversely, stores only dashboard JSON and user preferences in its own database (often SQLite or PostgreSQL), making it relatively stateless regarding metrics. When designing for compliance frameworks like ISO 27001, this separation allows you to apply different retention policies and access controls to raw metrics versus visualizations.

How do you configure Prometheus for production reliability?

Default Prometheus configurations are designed for development, not production. A common mistake I see in audits is teams running with default retention settings and no resource limits, leading to disk exhaustion during traffic spikes. Production configuration requires explicit attention to storage, security, and scrape optimization.

Persistent Storage and Retention

Always mount a Persistent Volume Claim (PVC) to /prometheus. For most workloads, start with 50GB and set retention by both time and size to prevent outages:

# prometheus.yml production snippet
global:
  scrape_interval: 15s
  evaluation_interval: 15s

storage:
  tsdb:
    path: /prometheus
    retention.time: 30d
    retention.size: 45GB  # Leave headroom below PVC size

scrape_configs:
  - job_name: 'kubernetes-nodes'
    kubernetes_sd_configs:
      - role: node
    relabel_configs:
      - source_labels: [__meta_kubernetes_node_label_kubernetes_io_os]
        action: keep
        regex: linux

Setting retention.size slightly below your actual PVC capacity prevents Prometheus from crashing when the disk fills up. The TSDB compaction process needs free space to operate; hitting 100% utilization corrupts the WAL (Write-Ahead Log).

Securing the Scrape Endpoint

Prometheus exposes all collected metrics on /metrics without authentication by default. In shared networks or multi-tenant clusters, this leaks sensitive operational data. Always place Prometheus behind a reverse proxy with mTLS or basic auth, or use the built-in web.config.yml for TLS termination if running standalone. For Kubernetes environments, network policies should restrict ingress to the Prometheus port (9090) only from Grafana and Alertmanager pods.

How do you set up Grafana securely with persistent dashboards?

Grafana's default admin/admin credentials and ephemeral storage are unacceptable for any team treating infrastructure seriously. Secure setup involves three pillars: authentication integration, configuration as code, and datasource provisioning.

  1. Disable Default Admin: Set GF_SECURITY_ADMIN_PASSWORD via secrets manager or disable the admin user entirely in favor of SSO. Never leave default credentials active past initial bootstrap.
  2. Provision Datasources: Use YAML provisioning files instead of UI configuration. This ensures every environment has identical datasource UIDs, preventing broken dashboards during migration.
  3. Persist Dashboards as Code: Store dashboard JSON in Git. Use Grafana's provisioning directory or tools like Grizzly to sync changes. UI-only edits are lost on restart and unauditable.
# /etc/grafana/provisioning/datasources/prometheus.yaml
apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    uid: prometheus-prod  # Fixed UID for dashboard portability
    url: http://prometheus:9090
    access: proxy
    isDefault: true
    jsonData:
      timeInterval: '15s'
      httpMethod: POST
    editable: false  # Prevent UI drift

Setting editable: false enforces GitOps discipline. Engineers can still create temporary exploratory dashboards, but canonical views remain version-controlled. This pattern aligns with the principles discussed in GitOps with ArgoCD declarative Kubernetes deployments, extending declarative management to observability.

How do you implement effective alerting without fatigue?

Alert fatigue destroys on-call effectiveness. The Prometheus and Grafana full monitoring stack includes Alertmanager specifically to solve this through grouping, inhibition, and silencing. Never send raw Prometheus alerts directly to Slack or PagerDuty; always route through Alertmanager.

PrometheusFiring AlertsGroup By ClusterInhibit If DownSilence WindowRoute MatchSeverity LabelPagerDutySlack OpsEmail Report
Alertmanager processing pipeline demonstrating grouping, inhibition rules, and multi-receiver routing for the monitoring stack.

Configure grouping by logical boundaries (cluster, service, namespace) rather than individual alerts. A single node failure triggering 50 disk, CPU, and network alerts should arrive as one grouped notification. Inhibition rules suppress downstream symptoms when upstream causes are known — if a node is unreachable, silence all container-level alerts on that node. This reduces noise by 60-80% in typical microservice environments.

# alertmanager.yml
route:
  group_by: ['cluster', 'namespace', 'alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'slack-default'
  routes:
    - match:
        severity: critical
      receiver: 'pagerduty-critical'
      continue: false

inhibit_rules:
  - source_match:
      alertname: 'NodeDown'
    target_match:
      severity: 'warning'
    equal: ['instance']

For teams adopting AI-assisted operations, clean alert metadata is essential. Well-labeled alerts feed directly into tools covered in AI-powered log analysis find incidents faster, enabling automated correlation and root cause suggestion.

Prometheus and Grafana full monitoring stack vs managed alternatives?

Choosing between self-hosted and managed depends on team size, compliance requirements, and budget. While managed services reduce operational overhead, self-hosting offers cost predictability and data sovereignty critical for many Nepal-based organizations and regulated industries.

CriteriaSelf-Hosted StackManaged (AWS/GCP/Grafana Cloud)
Data SovereigntyFull control, air-gap capableVendor-dependent, region-limited
Cost at ScalePredictable (compute + storage)Metric-volume based, can spike
Operational OverheadHigh (upgrades, scaling, backups)Low (vendor handles ops)
Compliance AuditDirect evidence collectionSOC2 reports, limited custom proof
Custom IntegrationsUnrestricted plugin/exporter accessMay restrict certain plugins/queries

In my experience helping Nepali fintech companies achieve compliance, self-hosted stacks often win on data residency requirements. However, for startups with <3 engineers, managed Grafana Cloud's free tier provides better ROI until scale justifies dedicated ops time. The break-even point typically occurs around 500GB/month of metrics ingestion or when specific compliance evidence collection becomes mandatory.

Monthly Metrics Volume (GB)Monthly Cost ($)Self-HostedManagedBreak-even ~500GB1005001000
Cost trajectory comparison between self-hosted Prometheus and Grafana full monitoring stack and managed alternatives across scaling volumes.

Deploy Your Monitoring Stack With Confidence

A properly configured Prometheus and Grafana full monitoring stack transforms reactive firefighting into proactive capacity management. Start with persistent storage, enforce authentication from day one, and treat alert routing as code. These foundations support everything from basic uptime checks to advanced SLO tracking and AI-driven anomaly detection. If your team needs help designing an audit-ready observability platform or optimizing an existing deployment, reach out to discuss your infrastructure requirements.

Frequently Asked Questions

It combines Prometheus for metrics collection and alerting with Grafana for visualization. This open-source pairing provides end-to-end observability for infrastructure, applications, and cloud services without licensing fees in 2026.

Define both services in a docker-compose.yml file with persistent volumes. Map port 9090 for Prometheus and 3000 for Grafana, then run docker compose up -d to deploy the complete monitoring stack locally.

Yes, add Prometheus as a native data source in Grafana settings. Enter the service URL and click Save & Test to enable direct PromQL queries for dashboards and alerts.

Username admin and password admin. Change these immediately via the CLI or environment variables before exposing the stack to any network.

Production instances typically require 8GB to 16GB RAM depending on cardinality and retention. Monitor heap usage and adjust GOMAXPROCS to prevent out-of-memory crashes during high ingestion periods.

Set global scrape_interval to 15s in prometheus.yml for most workloads. Override per job for slow exporters, ensuring evaluation rules align with scrape timing to avoid missing data points.

High cardinality labels cause exponential TSDB growth. Audit label values using promtool check config and enforce relabeling rules to drop unnecessary metadata before ingestion reaches disk.

Mount a host volume to /var/lib/grafana/dashboards and configure provisioning YAML files. This ensures dashboard definitions survive redeployments and remain version-controlled alongside your infrastructure code.

No. Prometheus handles metrics only. Integrate Tempo or Jaeger for traces and link them within Grafana dashboards using trace IDs stored as metric labels.

Place nginx or Traefik reverse proxy in front with TLS termination and basic auth. Never expose port 9090 publicly, as Prometheus lacks built-in authentication mechanisms.

Use rate() for trend analysis over longer windows. Reserve irate() for volatile, short-term spikes where you need the instant slope between the last two samples.

Define YAML rule files with expr, for, and annotations fields. Load them via rule_files in config and connect Alertmanager to route notifications to Slack, PagerDuty, or email.

Yes. Deploy kube-prometheus-stack Helm chart to auto-discover pods, nodes, and services. It includes preconfigured exporters, recording rules, and Grafana dashboards tailored for Kubernetes environments.

Create recording rules for expensive aggregations. Precompute frequent queries into new metrics to shift processing load from read time to write time, improving dashboard responsiveness significantly.

Yes. Both projects are Apache 2.0 licensed. You pay only for underlying compute, storage, and operational overhead when self-hosting in production environments.