Cloudflare GraphQL CDN Analytics Security Engineering React Open Source

I Built an Enterprise Edge Intelligence Dashboard on Top of Cloudflare's GraphQL API — Here's Exactly How

Most teams stop at the Cloudflare UI. But the real power is in the API. Here's what becomes possible when you query it directly — batched, real-time, across 100+ zones at once.

Estimated read: 9 min Audience: Engineers, Platform Teams, Security Practitioners

The Problem No One Talks About

If you run a large estate on Cloudflare — dozens of zones, multiple teams, production and non-production environments — the Cloudflare dashboard starts to break down. It is designed for a single zone, not a portfolio.

Here is what the status quo looks like in practice:

This is not a workflow problem. It is a data access problem. All of that information exists — Cloudflare stores it — but it is locked behind a UI built for one zone at a time.

The Cloudflare Analytics GraphQL API can query up to 10 zones in a single request, return 30 days of daily traffic, and expose WAF events, bot scores, cache ratios, bandwidth bytes, and HTTP error codes — all in one call. Almost nobody uses it this way.

I built FlareSight to solve this. It is an open-source React dashboard that queries the Cloudflare GraphQL Analytics API in batches, processes the data client-side, and surfaces everything across your entire zone portfolio in a single view.


What the Cloudflare GraphQL API Can Actually Do

Most engineers know Cloudflare has a REST API. Fewer know about the GraphQL Analytics API at /client/v4/graphql. It is a different surface entirely, and it is the right tool for analytics workloads.

Here are the datasets it exposes that power FlareSight:

DatasetWhat it containsLimit
httpRequests1dGroupsDaily traffic: requests, cached requests, bytes, cached bytes, page views — per zone30 days
httpRequests1hGroupsHourly traffic broken down by datetime — for trend charts72 hours
httpRequestsAdaptiveGroupsRequest-level data with country, response status, HTTP method, bot score dimensions10,000 rows
firewallEventsAdaptiveGroupsWAF and firewall events: action (block/challenge/log), source, rule ID, client IP, ASN, country, user agent10,000 rows

The key insight is the zoneTag_in filter — you can pass an array of zone IDs and get data for all of them in one query. That is what makes a portfolio-wide dashboard feasible.

The Batching Pattern

Cloudflare caps the zoneTag_in array at 10 zones per request. If you have 100 zones, you need 10 batched requests. Here is the exact pattern FlareSight uses:

// Split zone IDs into chunks of 10
const batchZones = (zoneIds) => {
  const batches = [];
  for (let i = 0; i < zoneIds.length; i += 10) {
    batches.push(zoneIds.slice(i, i + 10));
  }
  return batches;
};

// Execute batches sequentially with 250ms spacing
// to stay under the rate limit (4 req/sec)
for (const batch of batches) {
  const data = await graphqlRequest(query, { zoneIds: batch, start, end });
  allResults.push(...data.viewer.zones);
  await sleep(250);
}

With this pattern, 100 zones load in roughly 10 sequential requests — about 3–4 seconds. The rate limiter prevents 429s, and a 2-minute in-memory cache means subsequent navigations are instant.

The Core GraphQL Query (Traffic + Cache)

Here is the actual query that powers the Zone Portfolio and Performance modules — pulling 30 days of daily traffic with cache metrics for a batch of zones:

query ($zoneIds: [String!], $start: Date!, $end: Date!) {
  viewer {
    zones(filter: { zoneTag_in: $zoneIds }) {
      zoneTag
      httpRequests1dGroups(
        limit: 30
        filter: { date_geq: $start, date_leq: $end }
        orderBy: [date_ASC]
      ) {
        sum {
          requests
          cachedRequests
          bytes
          cachedBytes
          pageViews
        }
        dimensions {
          date
        }
      }
    }
  }
}

From requests and cachedRequests alone you get cache hit rate. From bytes and cachedBytes you get bandwidth savings. From requests - pageViews you get API traffic ratio — the split between human and machine traffic, with no extra query.

WAF and Threat Data

The security and threat modules use firewallEventsAdaptiveGroups combined with httpRequestsAdaptiveGroups. The critical thing most implementations miss: WAF events only capture traffic that triggered a firewall rule. Organic attacks — credential stuffing against your login endpoint, reconnaissance scanning 404s, API abuse returning 401s — come from httpRequestsAdaptiveGroups filtered on edgeResponseStatus_geq: 400.

FlareSight merges both datasets into unified attack instances:

// Dataset 1: WAF-triggered events
firewallEventsAdaptiveGroups(
  limit: 10000
  filter: { datetime_geq: $since }
) {
  count
  dimensions {
    action        # block / challenge / log
    source        # waf / rateLimit / firewallRules
    ruleId
    clientIP
    clientAsn
    clientCountryName
    clientRequestPath
    edgeResponseStatus
    userAgent
  }
}

// Dataset 2: HTTP errors (organic attacks, no WAF trigger)
httpRequestsAdaptiveGroups(
  limit: 10000
  filter: {
    datetime_geq: $since
    edgeResponseStatus_geq: 400
  }
) {
  count
  dimensions {
    clientIP
    clientCountryName
    edgeResponseStatus
    clientRequestPath
  }
}

The merged data then feeds a classifier that maps raw rule IDs and behaviour patterns into named attack categories: SQL Injection, XSS, DDoS (L7), Credential Stuffing, Reconnaissance Scanning, API Abuse, Content Scraping. No external threat intel service required — just pattern matching on what Cloudflare already gives you.


What FlareSight Actually Builds From This

Seven intelligence modules, all driven by the API calls described above:

1. Zone Portfolio Health

Every zone gets auto-graded A–F on cache efficiency. "Zombie" zones — zero traffic for 30+ days — are flagged automatically. Zones with low cache offload that are silently driving up your origin egress costs are highlighted with estimated monthly impact.

2. Performance Intelligence

7-day trend charts of cache hit rate and bandwidth savings per zone. The grading engine uses industry benchmarks: above 85% cache hit rate is an A, below 40% is an F. Per-zone recommendations (e.g. "Enable Tiered Cache", "Tune Browser TTL") are generated from the same data — no separate API call needed.

3. Compliance Audit

This module uses the Cloudflare REST Zone Settings API (not GraphQL) to check SSL/TLS mode, HSTS, WAF status, and Bot Fight Mode per zone. Every zone gets a 0–100 security score. The result is a filterable table you can export to CSV — ready for an auditor or a security review.

4. Security Operations

Real-time WAF block and challenge events across all zones. Block vs. managed challenge vs. log breakdown. Rule effectiveness ranking — which WAF rules are firing most frequently across your entire portfolio. Per-zone threat severity scoring with a searchable table.

5. Threat Deep Dive

The campaign analysis engine groups raw events by source IP and behaviour, then classifies them. It surfaces top malicious ASNs, targeted endpoints, and attack method breakdown. A webhook payload builder generates structured JSON for SOC integrations (Slack, PagerDuty, SIEM) directly from the UI.

6. ROI Calculator

Computes estimated annual bandwidth egress savings at $85/TB based on actual cached bytes from the API. Cache hit rate, cached bandwidth in TB, and CPU offload savings are surfaced as top-line KPIs — the kind of numbers that matter to an executive, derived entirely from cachedBytes in the GraphQL response.


The Current Constraint — and What the Roadmap Unlocks

The Cloudflare GraphQL API has a hard limit: 30 days of daily-granularity data, and 72 hours of hourly data. Trend charts, campaign history, and period-over-period comparisons are all bounded by this window.

Today FlareSight works around this with browser localStorage — every time the dashboard loads, it snapshots the current campaign data and stores it locally. This gives a rolling 30-day history of attack campaigns on that machine, with no backend database. It is a pragmatic solution. It is also an obvious ceiling.

What a persistence layer unlocks: with a backend that snapshots Cloudflare data on a schedule, you can answer questions the API alone never can.

Redis + Scheduled Jobs

The simplest upgrade: a Node.js cron job runs every hour, calls the GraphQL API for all zones, and writes the results to Redis with a time-series key structure. The dashboard queries Redis instead of Cloudflare directly. You gain:

PostgreSQL + Time-Series Extension

For deeper analytics: store every daily snapshot in Postgres with TimescaleDB. This enables SQL aggregations over arbitrary date ranges, per-zone regression analysis, and scheduled PDF reports generated server-side. Traffic anomaly detection becomes trivial — a simple query comparing last week's p95 to the current hourly rate.

Cloudflare Workers + D1

The most elegant path for teams already on Cloudflare: deploy a Worker on a cron trigger that writes zone snapshots to D1 (Cloudflare's serverless SQLite). The dashboard queries the Worker instead of the GraphQL API directly. Zero infrastructure, zero operational overhead — and the Worker runs at the edge, so the latency to the Cloudflare API is minimal. This is the direction FlareSight will move.

Real-Time Alerting

Once data is in a persistent store, alerting becomes straightforward. A spike in firewallEventsAdaptiveGroups beyond a configurable threshold triggers a Slack webhook. A zone dropping below 60% cache hit rate sends a PagerDuty alert. Traffic anomaly detection without a third-party observability platform.


The Bigger Point About Cloudflare's API Surface

Most teams interact with Cloudflare through the dashboard or Terraform. The API surface is far richer than most people realise:

API SurfaceWhat you can build with it
GraphQL Analytics APITraffic analytics, WAF events, bot scores, cache metrics — all queryable in batch
Zone Settings REST APICompliance audits, drift detection, automated remediation
Firewall Rules APIProgrammatic WAF rule management, rule effectiveness analysis
Logpush APIStream raw logs to S3/R2/BigQuery for unlimited retention and custom analytics
Workers Analytics EngineCustom metrics emitted from Workers, queryable via SQL — build your own datasets
Radar APIInternet-wide threat intelligence — BGP route leaks, DDoS attack trends, top attack origins globally

FlareSight only uses the first two. Logpush alone would eliminate the 30-day analytics window entirely by streaming every HTTP request to a data store you control. Workers Analytics Engine would let you emit custom business metrics — revenue per zone, SLA breach events, conversion rates by CDN PoP — and query them with the same GraphQL interface.

The platform is genuinely more powerful than it is given credit for. The dashboard is a consumer product. The API is an enterprise data platform.


Get the Code

FlareSight is open source. The full source — React frontend, Node.js proxy backend, all seven analytics modules — is on GitHub: github.com/ibm-webmethods/FlareSight

To run it locally you need a Cloudflare API token with Analytics:Read, Firewall Services:Read, and Zone:Read scopes. The backend is a thin Node.js CORS proxy — it never stores credentials. Everything else runs in the browser.

The codebase is structured so the Cloudflare API layer is entirely isolated in src/api/cloudflare/. Swapping in a Redis-backed persistence layer or connecting to Logpush is a matter of replacing the API module without touching any of the processing or UI code.


What I Learned


FlareSight is built with React 19, Vite 7, Tailwind CSS, and Recharts. The Cloudflare GraphQL Analytics API is available on all plan tiers; Enterprise plans unlock higher row limits and Bot Management score dimensions. All code referenced in this article is available in the open-source repository.