Define use cases and constraints
Use cases (in scope)
- User searches for someone and sees the shortest path to that person.
- Service has high availability.
Constraints and assumptions
- Traffic is not evenly distributed; some searches are popular, others run once.
- The graph does not fit on one machine; edges are unweighted.
- 100 million users, ~50 friends each → 5 billion friend relationships.
- 1 billion friend searches/month.
Usage
- 400 searches/second.
Sketch the high-level design
- Entry
The client reaches a web server and Search API.
- Traversal
The user-graph service explores graph neighbors with breadth-first search.
- Lookup
A lookup service routes person IDs to their graph shard.
- Person servers
Person servers A, B, and C hold the illustrated shards.
The graph service performs breadth-first search; lookup finds the shard that owns an ID.
How to read this model
A traversal carriage beside a shard-location catalogue. The object is a teaching analogy. Inspecting a part highlights its role; it does not execute or simulate the software. Cabinet trays are records, workpieces are data, and latches are checks. Unless an explanation states a quantity, compartments and sample workpieces do not denote data counts. Part dimensions are not a quantitative scale.
Define the core components
Without the scale constraint, an unweighted shortest path is a plain BFS. At scale, users are sharded across Person Servers, reached through a Lookup Service.
- Client → Web Server → Search API → User Graph Service.
- The User Graph Service uses the Lookup Service to find the Person Server holding a given
person_id, then runs BFS usingfriend_idsas adjacent nodes.
Scale the design
- Entry
DNS, a load balancer, and web servers precede the Query API.
- Graph service
The user-graph service performs the traversal.
- Lookup and cache
The lookup service routes IDs; memory cache supplies suitable hot results.
- Batched shards
Person servers A, B, and C serve batched shard requests under the graph’s ownership rule.
Caching and batching reduce machine-to-machine calls during graph traversal.
How to read this model
A traversal console beside cached lookups and shard cabinets. The object is a teaching analogy. Inspecting a part highlights its role; it does not execute or simulate the software. Cabinet trays are records, workpieces are data, and latches are checks. Unless an explanation states a quantity, compartments and sample workpieces do not denote data counts. Part dimensions are not a quantitative scale.
- 400 reads/s → serve person data from a memory cache; helps repeat searches and well-connected people.
- Cache complete or partial BFS traversals; batch-compute offline and store in NoSQL.
- Reduce machine jumps by batching friend lookups on the same Person Server; shard by location.
- Run two BFS searches at once (source and destination) and merge paths.
- Start BFS from high-degree people (fewer degrees of separation).
- Set a hop/time limit before asking the user to continue.
Additional talking points
- SQL scaling patterns and NoSQL: see database.
- A graph database (Neo4j) would be natural here if not for the constraint: see graph database.