Skip to content

Webhook Analytics — Complete Guide to Delivery Metrics

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Webhook Analytics. We cover key concepts, practical examples, and best practices to help you master this topic.

Webhook analytics tracks delivery success rates, latency, retry counts, event volumes, and consumer health metrics to monitor and optimize webhook infrastructure performance at scale.

What You'll Learn

  • Key metrics for webhook delivery monitoring
  • Tracking delivery latency and success rates
  • Building dashboards for webhook health

Why It Matters

Without analytics, webhook failures go unnoticed until consumers complain. Monitoring delivery metrics helps detect issues early, identify problematic consumers, and optimize delivery infrastructure.

Real-World Use

Durga Antivirus Pro webhook analytics dashboard shows: events delivered per minute (2,500 avg), success rate (99.2%), p95 delivery latency (340ms), and retry distribution. Alerts fire when success rate drops below 98%.

flowchart LR
    E["Events Emitted"] --> M["Metrics Pipeline"]
    M --> S["Success Rate"]
    M --> L["Latency"]
    M --> R["Retry Count"]
    M --> V["Volume"]
    M --> H["Consumer Health"]
    S --> G["Grafana Dashboard"]
    L --> G
    R --> G
    V --> A["Alert Manager"]
    style M fill:#dbeafe,stroke:#2563eb

Code Examples

from prometheus_client import Counter, Histogram, Gauge
import time

# Metrics definitions
delivery_total = Counter('webhook_deliveries_total', 'Total webhook deliveries',
                          ['consumer', 'status'])
delivery_latency = Histogram('webhook_delivery_seconds', 'Delivery latency',
                              ['consumer'], buckets=[0.1, 0.5, 1.0, 2.0, 5.0, 10.0])
retry_counter = Counter('webhook_retries_total', 'Total delivery retries',
                         ['consumer'])
circuit_breaker_gauge = Gauge('webhook_circuit_breaker', 'Circuit breaker state',
                                ['consumer'], ['open', 'closed', 'half_open'])

def deliver_with_metrics(consumer, url, event):
    start = time.time()
    try:
        resp = requests.post(url, json=event, timeout=10)
        status = 'success' if resp.ok else 'failed'
        delivery_total.labels(consumer=consumer, status=status).inc()
        delivery_latency.labels(consumer=consumer).observe(time.time() - start)
        return resp.ok
    except Exception as e:
        delivery_total.labels(consumer=consumer, status='error').inc()
        retry_counter.labels(consumer=consumer).inc()
        return False

Expected output: Prometheus metrics track delivery count, latency, and retries per consumer.

// Webhook analytics logger
class WebhookAnalytics {
  constructor() {
    this.events = [];  // In production: write to time-series DB
  }

  logDelivery(eventId, consumerUrl, status, latencyMs, attempt) {
    this.events.push({
      eventId,
      consumerUrl,
      status,
      latencyMs,
      attempt,
      timestamp: new Date().toISOString(),
    });

    // Calculate rolling metrics
    const window = this.events.filter(e =>
      Date.now() - new Date(e.timestamp) < 300000
    );

    const successRate = (window.filter(e => e.status === 'success').length / window.length * 100).toFixed(1);
    const avgLatency = (window.reduce((s, e) => s + e.latencyMs, 0) / window.length).toFixed(0);
    const retryRate = (window.filter(e => e.attempt > 1).length / window.length * 100).toFixed(1);

    console.log({
      period: '5m',
      totalDeliveries: window.length,
      successRate: `${successRate}%`,
      avgLatency: `${avgLatency}ms`,
      retryRate: `${retryRate}%`,
    });
  }
}

const analytics = new WebhookAnalytics();
analytics.logDelivery('evt_123', 'https://consumer.com/webhook', 'success', 245, 1);

Expected output: Rolling 5-minute analytics window shows delivery metrics.

# Consumer health report generator
from datetime import datetime, timedelta

class HealthReport:
    def __init__(self, db):
        self.db = db

    def generate_report(self, consumer_id, hours=24):
        cutoff = datetime.utcnow() - timedelta(hours=hours)
        deliveries = self.db.query(
            "SELECT status, latency, attempt FROM deliveries "
            "WHERE consumer_id = ? AND created_at > ?",
            (consumer_id, cutoff)
        )

        total = len(deliveries)
        if total == 0:
            return {'consumer_id': consumer_id, 'status': 'no_data'}

        successes = sum(1 for d in deliveries if d['status'] == 'success')
        latencies = [d['latency'] for d in deliveries if d['latency']]
        retries = sum(1 for d in deliveries if d['attempt'] > 1)

        return {
            'consumer_id': consumer_id,
            'period_hours': hours,
            'total': total,
            'success_rate': round(successes / total * 100, 1),
            'avg_latency_ms': round(sum(latencies) / len(latencies), 0) if latencies else None,
            'p95_latency_ms': sorted(latencies)[int(len(latencies) * 0.95)] if latencies else None,
            'retry_rate': round(retries / total * 100, 1),
            'status': 'healthy' if successes / total > 0.98 else 'degraded',
        }

Expected output: Health report shows 24-hour delivery metrics including success rate and latency percentiles.

Common Mistakes

1. Not Tracking Per-Consumer Metrics

Aggregate metrics hide individual consumer problems. Track per-consumer success rates.

2. Ignoring Latency Percentiles

Average latency hides slow deliveries. Track p50, p95, and p99 latency.

3. No Alerting on Degradation

Collecting metrics without alerts means no one knows when thresholds are exceeded.

4. Only Tracking Success/Failure

Latency trends, retry distribution, and queue depth provide early warning before failures occur.

5. Short Retention Period

Keeping only 24 hours of metrics makes trend analysis impossible. Retain at least 30 days.

Practice Questions

  1. What are the top five webhook metrics to track?
  2. Why should you track per-consumer success rates separately?
  3. What is the difference between p50 and p99 latency?
  4. Why monitor retry distribution?
  5. How does webhook analytics help with capacity planning?

Answers:

  1. Success rate, latency (p50/p95/p99), delivery volume, retry count, circuit breaker state.
  2. A single failing consumer can drag down aggregate metrics; per-consumer tracking identifies the problem.
  3. p50 is median latency; p99 is the worst-case latency for 99% of requests (tail latency).
  4. Increasing retry rates indicate consumer health problems before complete failures occur.
  5. Volume trends and latency patterns help predict when infrastructure needs scaling.

Challenge: Build a webhook analytics dashboard with: real-time metrics (delivery rate, success rate, p95 latency), per-consumer breakdown, 24-hour trend graphs, and alerts when success rate drops below 98% or p95 latency exceeds 5s.

FAQ

What tools are commonly used for webhook analytics?

: Prometheus for metrics collection, Grafana for dashboards, Elasticsearch for log-based analytics.

How long should webhook metrics be retained?

: Raw metrics: 7-30 days. Aggregated metrics: 12-24 months for trend analysis.

What is a good webhook success rate target?

: 99.5%+ success rate for production webhook delivery.

How do you track webhook delivery latency?

: Measure time from event creation to successful delivery response, including retries.

Should webhook analytics include consumer response payloads?

: Only for debugging. Store response bodies briefly (24h) with restricted access.

Mini Project

Build a webhook analytics system with: Prometheus metrics (delivery counter, latency histogram, retry counter), per-consumer success rate tracking, a Grafana dashboard showing delivery volume, success rate, p50/p95/p99 latency, and alerts for degradation.

What's Next

Learn about Webhook security for securing delivery, or explore Webhook circuit breaker for protecting against unhealthy consumers.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro