Skip to content
Mustafa Erbay
Career · 9 min read · görüntülenme Türkçe oku

Prioritizing Monitoring and Alerting: My 3-Step Pragmatic Guide

Striking the right balance between monitoring and alerting in system and application operations has always been challenging. In this post, I'll explain my.

100%

What to monitor and what to alert on in systems is an area that proves its criticality with experience. Initially, I tried to set alerts for everything, then I drowned in the noise. Deciding what to monitor and what to alert on is an important engineering decision, especially when working with limited resources. In critical moments of a production ERP or in the background of my own side project, this prioritization has prevented sleepless nights.

In this post, I’ll explain how I’ve built my monitoring and alerting strategy over the years, detailing the steps I follow. For me, this isn’t just a technical topic; it’s directly related to operational maturity and team efficiency. Not every metric or log line should trigger an alarm; the important thing is to get the right signal at the right time.

Step 1: What Breaks if the Business Stops? Defining Business-Critical Metrics

The first and most important step is to identify the metrics that are the lifeblood of the business. A system can have hundreds of metrics indicating its performance, but not all of them are equally important. I always start by asking, “If this breaks, will we lose money, lose customers, or will operations stop?” When I was working with an ERP for a manufacturing company, this meant ensuring the uninterrupted flow of core business processes like order intake, production planning, shipping, and invoicing.

Once, at a large Turkish e-commerce site, I witnessed millions of liras in potential sales lost within hours due to a momentary problem with a payment gateway integration. It was then that I painfully learned that these types of metrics shouldn’t just be “monitored,” but should trigger an “alert” immediately. For such situations, I prioritize metrics that directly affect the output of business processes, rather than general system health indicators. For example, even if a database server’s CPU usage reaches 80%, if this doesn’t affect business workflows, a warning might suffice. But if our payment API’s error rate jumps from 1% to 5%, that’s a direct PagerDuty call.

When defining these metrics, I talk not only with the technical team but also with business units. What is their definition of “business stopping,” and which workflows are most critical? This helps me move beyond technical jargon and understand the real business impact. In my experience, software architecture is often not about software, but about organizational flow. Therefore, monitoring architecture should also mirror organizational flow.

Step 2: Monitor What Signals Before It Breaks: Proactive Metrics

While business-critical metrics say “there’s a problem now,” proactive metrics signal “there will be a problem soon.” These are indicators that provide clues about the system’s future behavior. Beyond obvious ones like disk fullness, there are other, more subtle proactive metrics. In my experience, correctly interpreting these metrics allows for proactive action and preventing major outages while they are still minor.

For example, in PostgreSQL, there’s a situation called WAL bloat. Excessive growth of transaction logs increases disk usage and degrades I/O performance. To monitor this, just looking at disk fullness isn’t enough; I track WAL size and growth rate using functions like pg_wal_lsn_diff. If the WAL size exceeds a certain threshold (e.g., 1GB) and the growth rate becomes abnormal, this is a warning for me, indicating that I need to immediately check VACUUM or replication settings.

-- Simple query for PostgreSQL WAL bloat tracking
SELECT
    pg_size_pretty(pg_current_wal_lsn() - '0/0'::pg_lsn) AS current_wal_size,
    (pg_current_wal_lsn() - pg_stat_replication.write_lsn) AS replica_lag_bytes
FROM pg_stat_replication
WHERE client_addr IS NOT NULL;

On the Redis side, OOM eviction policy selection and memory usage are critical. If I run Redis with maxmemory-policy noeviction and its memory fills up, it becomes unable to write new data. To prevent this, I monitor the used_memory metric and the evicted_keys count. An increase in the number of evicted keys is a sign that Redis is constantly trying to evict data and that memory is insufficient. This situation immediately requires a memory increase or optimization in the data model.

At this step, having a deep understanding of the internal workings of systems is a great advantage. Setting soft limits like cgroup memory.high in Linux and getting warnings when these limits are approached allows me to take precautions before a container is OOM-killed. Such detailed monitoring is usually what I focus on more when I put on my “system administrator” hat, and from my field experience, I know that these fine-tunings make a big difference.

Step 3: Filter the Noise, Alert Only What Requires Action

The fundamental difference between monitoring and alerting is that one is about collecting information (monitoring), while the other is about notifying when a situation requires intervention (alerting). If we try to set an alarm for everything we monitor, we quickly experience “alert fatigue.” The team starts ignoring constantly ringing alarms that don’t signal a real problem. This prolongs response time when a truly critical situation arises. I’ve made this mistake repeatedly in my own operations and learned my lesson.

My basic principle for alerting is: “If an alarm wakes me up in the middle of the night, it must be a truly urgent problem requiring intervention.” With this philosophy, I set the thresholds and triggering logic for alarms very carefully.

For example, I use fail2ban to block malicious requests to my servers. fail2ban internally catches specific patterns and bans IPs. Normally, fail2ban banning an IP is not an alarm; it means it’s doing its job. But if I see in fail2ban logs, for instance, more than 1000 bans in the last hour, this could be a DDoS attempt or a widespread scanning attack. This is an alert level. For this scenario, I set up a systemd unit that monitors fail2ban logs via journald and sends a notification when the number of bans exceeds a certain threshold.

# Example of filtering and counting fail2ban logs with journalctl
# Counts ban events in the last 1 hour
journalctl -u fail2ban.service --since "1 hour ago" | grep "Ban" | wc -l

Similarly, journald itself has rate limits. If a service logs too much, journald might start dropping these logs (rate limit). This can cause us to miss important logs. I pay attention to the RateLimitBurst and RateLimitIntervalSec settings for the systemd-journald service in journald. If I see a log indicating these limits have been reached, it gives me an alarm that I need to optimize the logging behavior of the relevant application. Such situations often work in conjunction with limits I assign to processes via cgroup, such as memory.high or CPUQuota.

Connecting Monitoring Data to Action Plans

Knowing what to do when we receive an alarm is as important as the alarm itself. Just getting a notification saying “Disk full!” is not enough. We also need to know which disk is full, which application is using this disk, how to clean it, or how to resolve the issue. For me, every critical alarm should have a “runbook” behind it. This runbook includes a roadmap for problem detection, initial intervention steps, temporary solutions, and the ultimate resolution.

In a production ERP, I prepared detailed runbooks for situations like PostgreSQL slowdowns. These runbooks include which metrics to check (CPU, I/O, active connections), which queries to run (slow queries, locked tables), how to interpret EXPLAIN ANALYZE outputs, and possible index strategies. Sometimes, I even add simple shell scripts containing basic troubleshooting commands to these runbooks.

The concept of observability also comes into play here. Not just metrics, but logs and traces also play a critical role in finding the root cause of a problem. When an application’s error rate increases, knowing just the number isn’t enough. We also need to know which requests are failing, the error’s stack trace, and which users are affected. In my systems, while collecting metrics with Prometheus, I gather logs in a central location with Loki or Elasticsearch. For traces, I use OpenTelemetry to see how a request travels between different services and where it gets stuck. Bringing these three together ensures that an alarm saying “There’s a problem!” also says “The problem is here, and you can solve it like this!”

This approach becomes even more important during architectural changes, especially when transitioning from monolith to microservices. Tracking the journey of a request in distributed systems can be much more complex than in a single monolith. Therefore, in architectures like event-sourcing or CQRS, I have to use the transaction outbox pattern to monitor idempotency issues and ensure that events are processed correctly.

My Techniques for Reducing Noise and Combating Alert Fatigue

Over the years, I’ve personally experienced how destructive alert fatigue can be. Constant, but insignificant, alarms eventually lead to real emergencies being overlooked. Therefore, reducing noise and only sending alerts that require action has become an operational discipline for me.

Some techniques I use include:

  • Deduplication (Grouping Recurring Alarms): Instead of sending a new notification every time the same error occurs repeatedly, I send the first notification and then group subsequent identical errors under that notification. This way, instead of “100 disk full alarms,” I receive a notification like “Disk full (repeated 100 times).”
  • Silencing: I temporarily silence alarms during planned maintenance windows or for known temporary issues. For example, during a VPS migration process, I silence the old server’s network alarms until the new server is up.
  • Escalation Policies: I initially send an alarm to only one team. If no action is taken within a certain period, it’s escalated to a higher-level team or a different channel (SMS, phone call).
  • Baselines and Anomaly Detection: Static thresholds are not always sufficient. I use systems that monitor metrics like an application’s normal traffic patterns and CPU usage during operation, and flag deviations from this baseline as anomalies. This is very useful, especially when I enable a new feature flag or perform a canary deployment.
  • Alert Review: I regularly review existing alarms (monthly or after every major incident). I weed out alarms that are no longer valid, produce false positives, or send unnecessary notifications. This also applies to alarms about systemd unit failures. Sometimes a systemd timer doesn’t work as expected and I get OOM-killed. In this case, I improve the alarm by linking it to a more specific reason than “OOM-killed.” Last month, I got OOM-killed after writing sleep 360, then I switched to polling-wait to reduce such errors.

These approaches are critically important, especially in complex bare-metal + container hybrid deployment environments. When monitoring disk fires or build OOM situations in an environment managed with Docker Compose, these filtering techniques allow me to take action only in situations that truly require intervention. Otherwise, it would be inevitable to drown under constantly ringing phones and incoming notifications. This is one of the most valuable lessons I’ve learned since the early years of my career.

Conclusion

Monitoring and alerting are the cornerstones of ensuring a system’s healthy operation. However, striking the right balance between the two comes with years of experience. The 3 steps I’ve outlined in this post – defining business-critical metrics, monitoring proactive signals, and filtering out noise to alert only what requires action – have been a roadmap for operational maturity for me.

Let’s not forget that this process is not a one-and-done task. As systems evolve and business needs change, these priorities must be continuously reviewed and updated. Every new feature, every new integration, can add a new layer to our monitoring and alerting strategy. With a pragmatic approach, learning from mistakes, and continuous improvement, we can build more resilient systems. In my next post, I’ll discuss how I monitor index strategies and performance regressions in PostgreSQL.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

How was this post?

Frequently Asked Questions

Common questions readers have about this article.

When balancing monitoring and alerting, which metrics should I prioritize?
I always start by asking, 'If this breaks, will we lose money, lose customers, or will operations stop?' Identifying business-critical metrics is crucial for getting the right signal at the right time amidst hundreds of metrics showing system performance. For example, when working with an ERP for a manufacturing company, this meant ensuring the uninterrupted flow of core business processes like order intake, production planning, shipping, and invoicing.
What tools can I use to build my monitoring and alerting strategy?
For me, monitoring and alerting tools are essential for tracking system performance and setting up alarms for critical metrics. For example, I use tools like Prometheus, Grafana, and Alertmanager. With these, you can monitor system performance in real-time, set up alarms for critical metrics, and intervene quickly.
What tradeoffs should I consider when building my monitoring and alerting strategy?
When building my monitoring and alerting strategy, I've learned that everything involves tradeoffs. For instance, if you set too many alarms, you can get overwhelmed by noise, but if you set too few, you might miss critical issues. For me, the key is to strike the right balance to get the right signal at the right time and monitor system performance effectively. For example, you might set stricter alarms for critical metrics while being more lenient for less critical ones.
What consequences can arise if I make mistakes in my monitoring and alerting strategy?
If you make mistakes in your monitoring and alerting strategy, you might fail to monitor system performance, miss critical issues, and experience operational problems. For me, it's crucial to continuously review and update the monitoring and alerting strategy as needed. For example, while monitoring system performance and setting alarms for critical metrics, you should constantly update your strategy to quickly detect and respond to errors.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Comments

Server-side AI Moderation

Comments are AI-moderated server-side and stored permanently.

?
0/2000

Server-side AI moderation

✉️ Free · No spam · Unsubscribe anytime

Get notified about new posts

New content and technical notes — straight to your inbox.

  • 📌
    Best of the week Single most-worth-reading post
  • 🔧
    Toolbox notes Real tools I used this week
  • 🧠
    Behind-the-scenes Notes that don't make it to blog

We don't spam. Unsubscribe anytime. · Tracked only by Umami (self-hosted, no Google).

Your Reading Stats

0

Posts Read

0m

Reading Time

0

Day Streak

-

Favorite Category

Related Posts