← Changelog

Crawl Intelligence Pipeline

Crawl 2026-06-26

Built a D1 + KV bot monitoring pipeline that logs every HTTP request, classifies crawlers by UA and ASN, and surfaces aggregated data on public dashboards — with zero D1 reads on page load.

What it does

Every HTTP request to leedriggers.com is intercepted by Cloudflare Worker middleware before the page handler runs. The middleware extracts the user-agent string, request path, country code, ASN, and Cloudflare’s cf-verified-bot flag, then writes a row to a D1 table (crawl_log).

A scheduled snapshot job (/api/snapshot) runs incrementally — it reads only rows newer than the last run, classifies each request into a named bot and group, and merges the results into persistent KV aggregates. Public dashboards read from KV only. No D1 on page load.

The incremental cursor pattern

The key to scalability is snapshot:meta.lastRun. Each run records its own timestamp to KV. The next run queries D1 for rows with ts > lastRun. This means:

No row cap, no pruning of crawl_log. The table grows indefinitely.

What gets tracked

All-time aggregates (indefinite retention):

Rolling windows:

Derived keys:

What I can see now

KV size constraint

KV values max out at 25MB. Per-path daily data grows the fastest — hence the 300-path cap and 90-day rolling window. All-time totals and daily counts are much smaller in practice. The site has never approached the limit, but the cap is a real constraint to watch as traffic scales.

← All entries