ayushsalampuriya.xyz Revise

System Design · Design Question

Design a Web Crawler

Discover and fetch pages at scale: URL frontier, politeness, dedupe, parsers, and storage.

1. Requirements

2. API / control plane

POST /seeds { "urls": ["https://example.com"] } GET /status { queueDepth, fetchQps, hostsBlocked } POST /hosts/{h}/pause

3. Main components

URL Frontier (priority queues per host) | Fetcher workers --HTTP GET--> Web | DNS cache / robots cache | Parser (extract links, canonical URL) | +--> Content Store (S3/HDFS) + metadata DB +--> Link Filter → enqueue new URLs to Frontier +--> Dedupe (URL seen, content fingerprint)

4. URL frontier

The frontier holds URLs to visit. Needs priority (PageRank/seed distance) and politeness (do not hammer one host).

Per-host queue + global scheduler: - Never fetch same host more than once per politeness interval - Prefer high-priority hosts/URLs - Persist frontier for crash recovery (Kafka / DB backed)

5. Data model

urls(url_hash PK, url, host, priority, next_fetch_at, last_status) robots(host, rules_blob, fetched_at) documents(doc_id, url_hash, storage_path, content_hash, fetched_at) links(from_doc, to_url_hash)

6. Deduplication

7. Politeness and robots

Fetch robots.txt → cache If Disallow matches path → skip Else wait until host's next_allowed_ts Identify crawler via User-Agent

8. Deep dive — scaling fetchers

9. Failure modes

10. Interview flow

  1. Seeds → frontier → fetch → parse → store → enqueue links.
  2. Call out robots + politeness.
  3. Dedupe URL/content.
  4. Priority + recrawl policy.
  5. Scale workers and persist frontier.

11. Freshness and priority

score(url) = f(pagerank, change_rate_estimate, product_importance) next_fetch_at = now + interval(score) News sites: short interval; archive pages: long interval

Change-rate can be learned from past Last-Modified / content-hash diffs. Do not recrawl the whole web at one frequency.

12. Distributed frontier

Quick revision

  • Frontier schedules URLs with priority and per-host politeness.
  • Always honor robots.txt; cache it.
  • Canonicalize + Bloom/seen-set to avoid re-fetch loops.
  • Parser extracts links; content goes to blob store + metadata.
  • Recrawl important pages more often.
  • Guard against spider traps with budgets and filters.
  • Persist frontier; ACK fetches for reliability.