Skip to content

AI crawler traffic (GPTBot/ClaudeBot) driving majority of Workers CPU bill #652

Description

@tiankaima

Summary

AI training crawlers — primarily GPTBot and ClaudeBot, with smaller contributions from Bytespider and YisouSpider — are crawling the public catalog SSR pages at very high volume. Each hit triggers a full SSR render plus Postgres queries, and is billed as Workers CPU time. This is the dominant contributor to the current Cloudflare bill.

Evidence (Workers Observability, last 24 h, logs head-sampled at 25%)

User-Agent Sampled requests Estimated actual req/day Avg CPU/request Estimated CPU/day
GPTBot 97,040 ~390,000 140 ms ~54M CPU-ms (~15 CPU-hours)
ClaudeBot 19,816 ~79,000 179 ms ~14M CPU-ms
Bytespider 1,208 ~4,800 52 ms ~0.25M CPU-ms
YisouSpider 200 ~800 34 ms negligible
Real users (browsers, dataaccessd, etc.) 3–60 ms negligible

Estimated cost: roughly 2B CPU-ms/month from GPTBot + ClaudeBot alone, i.e. on the order of $40–50/month at standard Workers CPU pricing — the bulk of the bill.

What they crawl

Almost exclusively catalog SSR pages:

  • /catalog/sections/{jwId} and /catalog/sections/{jwId}/{introduction,comments,exams,teachers,calendar}
  • /catalog/courses/{jwId}, /catalog/courses/{jwId}/sections

These URLs are enumerated for the crawlers by sitemap.xml (src/routes/sitemap.xml/+server.ts lists every non-retired course/section/teacher), and robots.txt (src/routes/robots.txt/+server.ts) currently allows all user-agents to crawl /catalog/*.

Why each hit is expensive

Every crawler hit executes the full request pipeline with zero edge caching:

  1. HTML responses get Cache-Control: no-store from src/hooks.server.ts:315-317 (catalog pages set no public cache headers of their own), so Cloudflare never serves them from cache.
  2. Each request instantiates a fresh PrismaClient + pg pool (see related issue: Prisma client is re-created per request), adding tens to hundreds of ms of pure CPU.
  3. Full SvelteKit SSR + Postgres queries via Hyperdrive for content that changes at most a few times per day.

Proposed remediation (already applied)

  • Block GPTBot and ClaudeBot at the Cloudflare zone level (bot/WAF rules) — done manually by maintainer
  • Optionally add explicit User-agent: GPTBot / ClaudeBot / Bytespider Disallow: / entries (or disallow /catalog/) in robots.txt for well-behaved crawlers
  • Track the two structural fixes in the linked issues (per-request Prisma client; no CDN caching for anonymous catalog pages) so that residual crawler traffic is cheap to serve

Resolution

Blocked at Cloudflare on 2026-07-25. Closing; the structural follow-ups are tracked in their own issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions