← HubSpot Interview Insights

HubSpot·Software Engineer·Onsite - System Design / Architecture·Intermediate

IntermediatePrefer not to say
Jun 2026

Summary

HubSpot system design round focused on a web crawler problem. The question had a lot of moving parts and the discussion went pretty deep into concurrency and testing, which I wasn't fully expecting for a coding screen.

Questions Asked (1)

Q1

Design a web crawler that starts from a given URL and uses a provided get_links(url) function to discover all pages under the same hostname. It should visit each URL at most once, use a fixed-size worker pool for concurrency, and return the full set of discovered URLs. Walk through your data structures, thread safety approach, and how you'd test it.

System DesignAlgorithms & Data StructuresTechnical Trade-offs
Author's notes

This looked manageable at first.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then outline a BFS-based crawler using a thread-safe queue and a shared visited set to ensure each URL is visited once. Explain how a fixed-size worker pool processes URLs concurrently, and discuss testing strategies including unit tests with mocked get_links and integration tests for concurrency.

Pro tip: Mention that you would normalize URLs (e.g., remove fragments, handle trailing slashes) before deduplication to avoid visiting the same page under different forms. Also, discuss how you'd handle edge cases like redirects, non-HTML content, and rate limiting to show production awareness.

1. Clarify requirements and constraints

Ask about expected scale, politeness policies, error handling, and whether the crawler should respect robots.txt. Confirm that only same-hostname URLs are crawled and that get_links is the only way to discover links.

2. Design data structures and concurrency model

Use a thread-safe queue (e.g., LinkedBlockingQueue) for URLs to visit and a concurrent set (e.g., ConcurrentHashMap.newKeySet) for visited URLs. A fixed-size worker pool (e.g., ExecutorService with N threads) pulls URLs from the queue, calls get_links, and enqueues new same-host URLs not yet visited.

3. Ensure thread safety and termination

Use atomic operations or locks to check-and-add to the visited set before enqueueing. Track active tasks (e.g., with a counter or phaser) to know when all workers are idle and the queue is empty, then signal completion.

4. Handle edge cases and optimizations

Normalize URLs (lowercase host, remove fragments, resolve relative paths) before deduplication. Handle exceptions from get_links gracefully, and consider backpressure or rate limiting to avoid overwhelming the target server.

5. Outline testing strategy

Write unit tests with a mock get_links that returns a controlled graph, verifying all URLs are visited exactly once. Add concurrency tests to ensure no race conditions, and integration tests with a local web server to validate real-world behavior.

Key Points to Mention

  • BFS traversal to discover all pages under the same hostname
  • Thread-safe data structures: concurrent queue and set
  • Fixed-size worker pool with ExecutorService or similar
  • URL normalization and deduplication before visiting
  • Graceful termination detection when queue is empty and workers are idle
  • Testing with mocks for unit tests and concurrency stress tests

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.