Web fundamentals, an interactive architecture walkthrough
Web crawler: how the architecture works
How a large-scale web crawler manages a URL frontier, stays polite per host, filters duplicate URLs and pages, and decides when to revisit.
This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate.
Interactive diagram
Overview
A web crawler discovers pages by fetching known URLs, extracting links from them, and fetching those in turn. Its core is a frontier: a prioritised to-do list of URLs, organised per host so the crawler can be fast overall and gentle on each site. Around it sit fetchers that obey robots.txt and rate limits, parsers that canonicalise URLs, two duplicate filters (one for URLs, one for page content), a store for the pages, and a scheduler that decides when to revisit.
Trade-offs and what changes at scale
Politeness caps the speed per host, so throughput comes from breadth, and a few huge sites dominate the wait. The seen-URL and content-fingerprint sets outgrow memory, so they use disk, caches and approximate structures, and a probabilistic filter can wrongly skip a small number of new URLs. Freshness competes with coverage for the same fetch budget, which is why revisit intervals follow how often pages change. JavaScript-rendered pages need a headless browser, which is far slower and costlier than plain HTTP. Spider traps, soft 404s and near-duplicate pages need heuristics rather than exact rules. Crawling must respect legal and site restrictions, and robots.txt is a convention, not access control. This is a simplified teaching model based on public information, not any company's actual crawler.
How it works, step by step
The walkthrough above, as text. Each step lights up the components named under it.
A crawl starts from seed URLs placed in the URL Frontier with a priority. The frontier is the crawler's to-do list; everything else exists to drain it politely and to refill it with links found on the way.
The frontier has priority queues in front and one queue per host behind them, as in the published Mercator design, so any one host's URLs are fetched serially. The Politeness Scheduler takes a URL only from a host whose waiting time has passed, which stops the crawler from hammering a small site.
The scheduler dispatches URLs to Fetcher Workers. There are many workers, but each host has at most one request in flight, so total speed comes from crawling many hosts at once rather than one host fast.
Before fetching a page, the worker checks the host's robots.txt rules in the Robots Cache, fetching and caching the file if needed. RFC 9309 says to avoid using a cached copy for more than 24 hours where possible, to treat a 4xx answer for the file as no restrictions, and to assume complete disallow if the file cannot be reached because of a server error.
The worker resolves the host name through a caching DNS Resolver. Name resolution is a known bottleneck for crawlers because each new host needs a lookup, so resolvers cache results and run lookups asynchronously.
The worker sends the HTTP request with a clear user agent, timeouts, a maximum size and a limit on redirects, and uses conditional headers (such as the ETag from the last visit) on revisits so unchanged pages cost little. Rate-limit or server-error responses make the host's delay longer.
The page is written to the Raw Content Store, typically packed into large archive files because billions of tiny files would be costly to manage, and its outcome (status, time, ETag) is recorded in Crawl Metadata.
A parse job goes to the Parser Workers, which extract links and text. Each link is made absolute and canonicalised (for example lower-casing the host and dropping fragments) so that different spellings of one URL are recognised as the same.
The content-seen test compares a fingerprint of the page with those already stored. The same page often exists under several URLs and on mirrors, and a match avoids processing or storing it again. Fingerprints, not full pages, are stored to keep the test cheap.
The URL-seen test filters out links already discovered. It stores fixed-size checksums of canonical URLs rather than the text, and puts a cache or probabilistic filter in front, because the set is too large for memory and lookups have little locality.
Only unseen URLs are added to the frontier, given a priority from signals such as link depth and site importance. Per-host limits on depth and URL count help stop spider traps, where a site generates endless distinct URLs (such as calendar pages).
Pages change, so the Crawl Scheduler reads the metadata to decide what is due for a revisit, giving frequently changing pages shorter intervals and static ones longer. Revisits go back into the frontier like any other URL.
Downstream consumers such as an indexer read the stored pages in batches. Keeping crawling separate from indexing lets each be scaled and re-run on its own, for example re-indexing without fetching again.
Observability tracks pages fetched per second, error and timeout rates per host, frontier size and the share of duplicates. A growing frontier with a falling fetch rate usually points to a politeness bottleneck or a trap.
Sequence diagram
The same walkthrough as a UML sequence diagram, one lane per layer or group (14 components in all), left to right in the order a request reaches them, numbered by step. A loop on a lane is a step that stays inside that group. Solid arrows are synchronous calls, dashed are asynchronous.
Key components
Schedulingdomain
- Crawl Scheduler: seeds, revisit timing, priorities
- Politeness Scheduler: one request per host at a time, with delays
- URL Frontier: priority queues feeding one queue per host
Fetchingdomain
- DNS Resolver: caching, asynchronous lookups
- Fetcher Workers: download pages with timeouts and size limits
- Robots Cache: robots.txt rules per host, with expiry
- Websites: the servers being crawled
Storagedomain
- Crawl Metadata: per-URL status, last fetch, ETag, change history
- Raw Content Store: fetched pages in large archive files
Processingdomain
- Content Fingerprints: hashes of page content for duplicate detection
- Parser Workers: extract links and text, canonicalise URLs
- URL Seen Store: canonical URL checksums already discovered
Downstream Consumers
- Downstream Consumers: search indexing, analytics, datasets
Observability
- Observability: fetch rate, error rate, frontier size
Sources
Public writing this explainer draws on. Read these for what the real systems actually do.
Make it yours
Copy this diagram and its walkthrough into your own workspace, then change anything: swap Postgres for DynamoDB, add a cache, rewrite the narration. Free, and it uses no AI credits.
Related walkthroughs
- URL shortenerHow a link shortener creates unique short keys, serves redirects from a cache in a few milliseconds, and counts clicks off the redirect path.
- Distributed rate limiterHow an API rate limiter shares token buckets across gateways, answers 429 with a retry hint, fails safely and sheds load when the system is stressed.
- Distributed cacheHow a distributed cache places keys with consistent hashing, replicates shards, evicts entries, invalidates on writes and resists stampedes.
This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate. Real systems differ in the details. Browse the library.