Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/graphql-api/patterns.md
1# GraphQL Analytics API Patterns & Best Practices23## Time-Series Queries45Use time dimension granularity matching your range (see Best Practices below).67```graphql8query TrafficTimeSeries($zoneTag: string!, $start: Time!, $end: Time!) {9viewer {10zones(filter: { zoneTag: $zoneTag }) {11httpRequestsAdaptiveGroups(12filter: { datetime_gt: $start, datetime_lt: $end }13limit: 100014orderBy: [datetimeFiveMinutes_ASC] # or datetimeHour_ASC for longer ranges15) {16count17dimensions { datetimeFiveMinutes }18sum { edgeResponseBytes }19ratio { status4xx status5xx }20}21}22}23}24```2526## Top-N Queries2728### Top Countries by Request Count2930```graphql31query TopCountries($zoneTag: string!, $start: Time!, $end: Time!) {32viewer {33zones(filter: { zoneTag: $zoneTag }) {34httpRequestsAdaptiveGroups(35filter: { datetime_gt: $start, datetime_lt: $end }36limit: 1037orderBy: [count_DESC]38) {39count40dimensions { clientCountryName }41}42}43}44}45```4647Use `orderBy: [sum_edgeResponseBytes_DESC]` for top paths by bandwidth. Add `edgeResponseStatus_geq: 400` to the filter for top error status codes.4849## Workers Analytics5051```graphql52query WorkersOverview($accountTag: string!, $start: Time!, $end: Time!) {53viewer {54accounts(filter: { accountTag: $accountTag }) {55workersInvocationsAdaptive(56filter: { datetime_gt: $start, datetime_lt: $end }57limit: 10058orderBy: [sum_requests_DESC]59) {60sum { requests errors subrequests wallTime }61quantiles { cpuTimeP50 cpuTimeP99 wallTimeP50 wallTimeP99 }62dimensions { scriptName }63}64}65}66}67```6869Filter by `scriptName` for a specific Worker. Add `datetimeFiveMinutes` dimension + `orderBy: [datetimeFiveMinutes_ASC]` for error rate over time.7071## Firewall / Security7273```graphql74query RecentFirewallEvents($zoneTag: string!, $start: Time!) {75viewer {76zones(filter: { zoneTag: $zoneTag }) {77firewallEventsAdaptive(78filter: { datetime_gt: $start }79limit: 5080orderBy: [datetime_DESC]81) {82action source clientIP clientCountryName userAgent83clientRequestHTTPHost clientRequestPath ruleId datetime84}85}86}87}88```8990For aggregated firewall stats, use `firewallEventsAdaptiveGroups` with `action: "block"` filter and group by `ruleId`, `source`, `datetimeHour`.9192## DNS Analytics9394```graphql95query DNSQueryVolume($zoneTag: string!, $start: Time!, $end: Time!) {96viewer {97zones(filter: { zoneTag: $zoneTag }) {98dnsAnalyticsAdaptiveGroups(99filter: { datetime_gt: $start, datetime_lt: $end }100limit: 500101orderBy: [datetimeFiveMinutes_ASC]102) {103count104dimensions { datetimeFiveMinutes }105}106}107}108}109```110111## Storage Analytics (Account-Scoped)112113R2, KV, and D1 use `date` (Date type) filters instead of `datetime` (Time type).114115```graphql116# R2 operations117r2OperationsAdaptiveGroups(filter: { date_geq: $start, date_leq: $end }, limit: 100, orderBy: [date_DESC]) {118dimensions { date bucketName actionType }119sum { requests }120}121122# KV operations123kvOperationsAdaptiveGroups(filter: { date_geq: $start, date_leq: $end }, limit: 100, orderBy: [date_DESC]) {124dimensions { date actionType }125sum { requests }126}127128# D1 analytics129d1AnalyticsAdaptiveGroups(filter: { date_geq: $start, date_leq: $end }, limit: 100, orderBy: [date_DESC]) {130dimensions { date databaseId }131sum { readQueries writeQueries rowsRead rowsWritten }132}133```134135## Cache Analytics136137```graphql138query CacheStatusBreakdown($zoneTag: string!, $start: Time!, $end: Time!) {139viewer {140zones(filter: { zoneTag: $zoneTag }) {141httpRequestsAdaptiveGroups(142filter: { datetime_gt: $start, datetime_lt: $end }143limit: 20144orderBy: [count_DESC]145) {146count147dimensions { cacheStatus }148sum { edgeResponseBytes }149}150}151}152}153```154155For cache hit ratio over time, use aliases to query the same dataset twice — once with `cacheStatus: "hit"` filter and once without — then compute the ratio client-side.156157## Multi-Dataset Queries158159A single request can query multiple datasets, avoiding extra HTTP round-trips:160161```graphql162query DashboardOverview($zoneTag: string!, $start: Time!, $end: Time!) {163viewer {164zones(filter: { zoneTag: $zoneTag }) {165httpTraffic: httpRequestsAdaptiveGroups(166filter: { datetime_gt: $start, datetime_lt: $end }, limit: 1167) { count sum { edgeResponseBytes } ratio { status4xx status5xx } }168firewallEvents: firewallEventsAdaptiveGroups(169filter: { datetime_gt: $start, datetime_lt: $end }, limit: 5, orderBy: [count_DESC]170) { count dimensions { action source } }171dnsQueries: dnsAnalyticsAdaptiveGroups(172filter: { datetime_gt: $start, datetime_lt: $end }, limit: 1173) { count }174}175}176}177```178179## AI & Gateway Analytics180181```graphql182# Workers AI inference183aiInferenceAdaptiveGroups(184filter: { datetime_gt: $start, datetime_lt: $end }, limit: 100, orderBy: [datetimeHour_DESC]185) {186count187sum { totalInputTokens totalOutputTokens totalRequestBytesIn }188dimensions { modelId datetimeHour }189}190191# AI Gateway requests192aiGatewayRequestsAdaptiveGroups(193filter: { datetime_gt: $start, datetime_lt: $end }, limit: 100, orderBy: [datetimeHour_DESC]194) {195count196dimensions { gateway provider model datetimeHour }197sum { cachedTokensIn cachedTokensOut uncachedTokensIn uncachedTokensOut }198}199```200201Both are account-scoped — nest under `accounts(filter: { accountTag: $accountTag })`.202203## Best Practices204205**Always include time filters.** Queries without time filters scan all data and are slow/expensive.206207**Match time granularity to range:**208209| Time Range | Recommended Dimension |210|------------|----------------------|211| < 6 hours | `datetimeMinute` or `datetimeFiveMinutes` |212| 6-48 hours | `datetimeFiveMinutes` or `datetimeFifteenMinutes` |213| 2-14 days | `datetimeHour` |214| 14+ days | `date` |215216**Use aliases** for querying the same dataset with different filters in one request.217218**Request only needed fields.** Extra dimensions and metrics increase query cost.219220## See Also221222- [README.md](README.md) - Overview, decision tree, dataset index223- [api.md](api.md) - Query structure, aggregation fields, filtering operators224- [configuration.md](configuration.md) - Authentication, client setup, introspection queries225- [gotchas.md](gotchas.md) - Rate limits, sampling, troubleshooting226