NikoTakSecuring the Web, One Threat at a Time.

Real-Time Anomaly Detection for Web Traffic with Grafana and ClickHouse

This post describes a real-time anomaly detection system for web traffic that we built with Grafana, ClickHouse and Python. It runs in production and detects DDoS attacks, bot campaigns and credential stuffing.

The short version: it processes 50,000 requests per second, raises an alert within 90 seconds, and produces 85% fewer false positives than the static thresholds it replaced.

Why thresholds weren't enough

Most monitoring alerts on static thresholds. That doesn't work well anymore. Attacks adapt to stay under the limits, and legitimate traffic has become more complicated too, with global users, mobile devices and very different usage patterns. The hard part is telling a harmless spike from an attack.

Ratios instead of raw volume

Instead of watching raw traffic volume, we compute ratios that describe behavior. These stay stable when legitimate traffic grows and change when something unusual happens.

Sessions and identity

Request patterns

Errors

Architecture

There are three components.

Grafana for visualization and alerting. It connects to ClickHouse natively, so queries run in under a second. Dashboards show anomalies with confidence intervals, detected events are annotated on the timeline, and alerts are routed by severity.

ClickHouse as the time-series engine. Its columnar storage suits analytical queries. Logs stream in from the web servers in real time, materialized views keep the metrics aggregated continuously, and the history provides the baselines.

A Python detection service, running in containers. It computes the metrics, builds feature vectors, and scores and classifies anomalies with confidence intervals.

Detection algorithms

No single algorithm catches everything, so the service runs several:

Each algorithm's output gets a confidence weight, and the outputs are checked against each other before an alert is raised. Requiring agreement between them is what keeps false positives low without losing sensitivity.

Results

MetricThresholdsOur systemChange
False positive rate23.4%3.5%85% reduction
Detection latency5-15 minutes30-90 seconds75% improvement
Attack coverage34%89%162% increase
Operational overheadHighLowSignificant reduction

Case 1: credential stuffing

A coordinated campaign hit the login endpoints from distributed IP addresses. Several indicators fired together:

The attack was detected and mitigated automatically within 2 minutes of starting, before it degraded service for legitimate users. The post-incident analysis confirmed a coordinated bot network using compromised credential databases.

Case 2: application-layer DDoS

This attack targeted the search function, which is expensive to run, while keeping overall request volume normal. Total traffic looked fine; what gave it away was the per-endpoint view:

We applied dynamic rate limiting to the affected endpoints only. Availability stayed above 99% throughout the attack, with little impact on users.