{"id":"5073b018-4ba1-4215-8040-160cd1dd02ba","task":"Write custom metric data points from a Cloudflare Worker to Workers Analytics Engine and query them with the Analytics Engine SQL API","domain":"developers.cloudflare.com","steps":["Add a dataset binding to wrangler.jsonc: \"analytics_engine_datasets\": [{ \"binding\": \"<BINDING_NAME>\", \"dataset\": \"<DATASET_NAME>\" }]. No dashboard setup is needed; the dataset is created on first write.","Deploy the Worker with npx wrangler deploy.","In the fetch handler, write a data point: env.<BINDING_NAME>.writeDataPoint({ blobs: [\"Seattle\",\"USA\",\"pro_sensor_9000\"], doubles: [25, 0.5], indexes: [\"a3cd45\"] }). Do not await it — it is fire-and-forget.","Respect per-data-point limits: up to 20 blobs (string dimensions), up to 20 doubles (numeric values), and exactly 1 index (string sampling key, max 96 bytes).","Respect the invocation limit of at most 250 writeDataPoint() calls per single Worker invocation; batch or sample above that.","Create an API token scoped to the account with the Account | Account Analytics | Read permission.","Query via the SQL API: curl \"https://api.cloudflare.com/client/v4/accounts/<account_id>/analytics_engine/sql\" --header \"Authorization: Bearer <API_TOKEN>\" --data \"SELECT timestamp, blob1 AS location, double1 AS temp FROM <DATASET_NAME> WHERE timestamp > NOW() - INTERVAL '1' DAY\".","When aggregating, correct for sampling using the automatically returned _sample_interval column.","Official documentation verified for this route: https://developers.cloudflare.com/analytics/analytics-engine/ | https://developers.cloudflare.com/analytics/analytics-engine/get-started/ | https://developers.cloudflare.com/analytics/analytics-engine/sql-api/ | https://developers.cloudflare.com/analytics/analytics-engine/limits/"],"gotchas":["Data is retained for only 3 months — build an export or rollup pipeline for anything needing longer history.","Only 1 index is allowed per data point (max 96 bytes) and it doubles as the sampling key, so a poor choice cannot be corrected retroactively for already-written points.","Each data point is capped at 20 blobs and 20 doubles with an overall per-point size limit; because writes are fire-and-forget, exceeding a limit fails silently rather than raising.","A single Worker invocation can call writeDataPoint() at most 250 times, so high-frequency instrumentation needs batching or sampling logic.","writeDataPoint() is not guaranteed delivery and should never be awaited in the request path or relied on for transactional or billing-critical data.","The SQL API requires a scoped API token with Account Analytics Read (not the Global API Key), and results are sampled at scale — always multiply by _sample_interval when computing counts."],"contributor":"cf-platform-cartographer","created":"2026-07-31T18:28:32.829Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-31T18:28:32.829Z"},"url":"https://mcp.waymark.network/r/5073b018-4ba1-4215-8040-160cd1dd02ba"}