Cloudflare Analytics Engine — time-series metrics at the edge.
Analytics Engine is a columnar time-series store built into Workers. It accepts structured metric events (called "data points") and makes them queryable via SQL through the Cloudflare API. It's purpose-built for high-cardinality metrics at scale — far cheaper and more appropriate than using KV or D1 for counters.
Included with Workers Paid plan. 10M data points free/month.
[[analytics_engine_datasets]]
binding = "METRICS"
dataset = "2nth_token_usage"
// Record a token usage event per AI call
env.METRICS.writeDataPoint({
blobs: [
clientId, // blob1 — searchable string
skillPath, // blob2
agentId, // blob3
model, // blob4 (e.g. 'claude-sonnet-4-6')
],
doubles: [
tokensIn, // double1 — input tokens
tokensOut, // double2 — output tokens
latencyMs, // double3 — request latency
estimatedCost, // double4 — cost in USD
],
indexes: [clientId], // index for fast filtering (one per writeDataPoint)
});
// GET usage per client for the past 7 days
const query = `
SELECT
blob1 AS client_id,
SUM(_sample_interval * double1) AS total_tokens_in,
SUM(_sample_interval * double2) AS total_tokens_out,
SUM(_sample_interval * double4) AS total_cost_usd,
COUNT() AS total_requests
FROM 2nth_token_usage
WHERE timestamp > NOW() - INTERVAL '7' DAY
GROUP BY blob1
ORDER BY total_cost_usd DESC
`;
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${accountId}/analytics_engine/sql`,
{
method: 'POST',
headers: { 'Authorization': `Bearer ${cfApiToken}` },
body: query,
}
);
const { data } = await response.json();
// After every Claude call, record usage
async function recordTokenUsage(params: {
clientId: string;
skillPath: string;
model: string;
tokensIn: number;
tokensOut: number;
latencyMs: number;
}, env: Env): Promise<void> {
const costUsd = (params.tokensIn * 3 + params.tokensOut * 15) / 1_000_000; // claude-sonnet-4-6 pricing
env.METRICS.writeDataPoint({
blobs: [params.clientId, params.skillPath, params.model],
doubles: [params.tokensIn, params.tokensOut, params.latencyMs, costUsd],
indexes: [params.clientId],
});
}
_sample_interval: The query engine may sample your data at high volumes. Always multiply aggregates by _sample_interval for accurate counts.