Chapter 64: Design LinkedIn
1. Requirements
Functional Requirements
- User Profiles: Create and manage professional profiles with work history, education, skills
- Connections: Send/accept connection requests, build professional network
- Feed: Post updates, articles, media; view personalized feed from connections
- Messaging: Real-time 1-on-1 and group messaging with read receipts
- Jobs: Post job listings, apply to jobs, receive recommendations
- Search: Search for people, jobs, companies, content
- People You May Know (PYMK): Connection recommendations based on mutual connections
Non-Functional Requirements
- Scale: 900M+ users, 58M+ companies, billions of connections
- Read-Heavy: 95% reads (feed browsing) vs 5% writes (posting)
- Availability: 99.99% uptime for core features
- Latency: Feed load <500ms, search <200ms, messaging <100ms
- Consistency: Eventual consistency acceptable for feed; strong consistency for connections/messaging
Scale Estimation
Connections per user: Average 500 connections
Feed posts: 100M posts/day
Messages: 500M messages/day
Searches: 200M searches/day
Storage: ~50 PB (profiles, posts, media, messages)
Capacity Estimation
Traffic
| Operation | Calculation | QPS | Peak QPS |
|---|---|---|---|
| Feed reads | 300M × 10 views/day = 3B/day | 35K QPS | 70K QPS |
| PYMK queries | 300M × 5/day = 1.5B/day | 17K graph traversals/sec | 34K graph traversals/sec |
| Messages (writes) | 500M/day | 6K writes/sec | 12K writes/sec |
| Messages (reads) | 10:1 read/write ratio | 60K reads/sec | 120K reads/sec |
Storage
| Data Type | Calculation | Total Size |
|---|---|---|
| Graph storage | 900M users × 500 connections = 450B edges × 50 bytes | 22TB |
| Feed cache | 300M users × 1KB feed cache | 300GB (fits in Redis cluster) |
| Search index | 900M profiles + 58M companies + 20M jobs | ~5TB Elasticsearch |
2. High-Level Design
Web/Mobile] subgraph API Gateway Layer Gateway[API Gateway
Rate Limiting] end subgraph Application Services ProfileSvc[Profile Service] ConnectionSvc[Connection Service] FeedSvc[Feed Service] MessageSvc[Message Service] JobSvc[Job Service] SearchSvc[Search Service] end subgraph Data Layer ProfileDB[(Profile DB
MySQL)] GraphDB[(Connection Graph
Neo4j/JanusGraph)] FeedCache[(Feed Cache
Redis)] MessageDB[(Message DB
Cassandra)] JobDB[(Job DB
PostgreSQL)] SearchIdx[(Search Index
Elasticsearch)] end subgraph Storage S3[Object Storage
S3/CDN
Profile Photos/Media] end subgraph Message Queue Kafka[Kafka
Event Streaming] end Client --> Gateway Gateway --> ProfileSvc Gateway --> ConnectionSvc Gateway --> FeedSvc Gateway --> MessageSvc Gateway --> JobSvc Gateway --> SearchSvc ProfileSvc --> ProfileDB ProfileSvc --> S3 ProfileSvc --> Kafka ConnectionSvc --> GraphDB ConnectionSvc --> Kafka FeedSvc --> FeedCache FeedSvc --> Kafka MessageSvc --> MessageDB MessageSvc --> Kafka JobSvc --> JobDB JobSvc --> SearchIdx SearchSvc --> SearchIdx SearchSvc --> GraphDB Kafka --> FeedSvc Kafka --> SearchIdx
3. Connection Graph
Graph Database Design
LinkedIn's connection network is fundamentally a graph problem. Use a specialized graph database like Neo4j or JanusGraph to efficiently query relationships.
Node and Edge Schema
// Node: User
{
userId: "u123",
name: "John Doe",
headline: "Software Engineer",
location: "San Francisco"
}
// Edge: Connection
{
from: "u123",
to: "u456",
timestamp: 1714512000,
status: "ACCEPTED" // PENDING, ACCEPTED, BLOCKED
}
Degree-Based Querying
- 1st Degree: Direct connections - simple edge traversal
- 2nd Degree: Friends of friends - 2-hop traversal
- 3rd Degree: Extended network - 3-hop traversal (limited for privacy)
// Cypher query for 2nd degree connections
MATCH (me:User {id: $userId})-[:CONNECTED]->(:User)-[:CONNECTED]->(friend2)
WHERE NOT (me)-[:CONNECTED]->(friend2) AND me.id <> friend2.id
RETURN DISTINCT friend2
LIMIT 100
People You May Know (PYMK)
PYMK is a key growth feature using multiple signals:
- Common Connections: Count mutual friends (strongest signal)
- Common Workplace: Same company, overlapping time periods
- Common Education: Same school, similar graduation year
- Common Skills: Overlapping skill endorsements
- Profile Views: People who viewed your profile
- Email Contacts: Imported email address book matches
Graph Partitioning
With 900M users and billions of connections, partition the graph:
- Geo-based: Partition by region (users connect locally more often)
- Hash-based: Consistent hashing on userId
- Replication: Replicate hot nodes (influencers with millions of connections)
4. Feed System
Feed Generation Approaches
| Approach | Pros | Cons |
|---|---|---|
| Pull Model (Fan-out on read) | Simple, no storage overhead | Slow for users with many connections |
| Push Model (Fan-out on write) | Fast reads (pre-computed) | Expensive writes for influencers |
| Hybrid Model | Best of both | More complexity |
LinkedIn's Hybrid Approach
- Regular Users: Push model - when user posts, fan-out to all connections' feeds
- Influencers (10K+ followers): Pull model - fetch their posts at read time
- Feed Cache: Store top 1000 posts per user in Redis sorted set (by timestamp/score)
Feed Ranking Algorithm
LinkedIn uses engagement-based ranking, not pure chronological:
FeedScore = W1 * Recency
+ W2 * ConnectionStrength
+ W3 * ContentRelevance
+ W4 * EngagementPrediction
// Factors:
// - Recency: Decay function (exponential or linear)
// - ConnectionStrength: 1st degree > 2nd degree, interaction history
// - ContentRelevance: Skills/interests match, hashtag similarity
// - EngagementPrediction: ML model predicting like/comment/share probability
Feed Architecture
Viral Content Detection
Detect trending posts and amplify them:
- Engagement Velocity: Likes/comments/shares per minute after posting
- Virality Coefficient: (Shares / Impressions) - high shares = viral
- Boost Distribution: Show viral content to 2nd/3rd degree connections
5. Search System
Search Scope
- People Search: Name, title, company, location, skills
- Job Search: Title, keywords, location, company, salary range
- Content Search: Posts, articles by keyword/hashtag
- Company Search: Company name, industry, size
Elasticsearch Index Design
// People Index
{
"userId": "u123",
"name": "John Doe",
"headline": "Senior Software Engineer at Google",
"location": "San Francisco, CA",
"skills": ["Java", "Python", "System Design"],
"currentCompany": "Google",
"pastCompanies": ["Facebook", "Amazon"],
"connections": 523,
"indexPriority": 8.5 // Influence score for ranking
}
// Job Index
{
"jobId": "j456",
"title": "Senior Backend Engineer",
"company": "Meta",
"location": "Menlo Park, CA",
"skills": ["Go", "Distributed Systems", "Kubernetes"],
"salary": "180k-250k",
"postedDate": "2026-05-10",
"applicants": 47
}
Search Ranking Factors
| Factor | Weight | Description |
|---|---|---|
| Text Relevance | 40% | BM25 score on query terms |
| Connection Degree | 25% | 1st > 2nd > 3rd degree |
| Profile Completeness | 15% | Photo, headline, experience |
| Activity Level | 10% | Recent posts, engagement |
| Premium Status | 10% | Paid users ranked higher |
Search Architecture
- Index Sharding: Shard by entity type (people, jobs, content) and geography
- Replication: 3 replicas per shard for high availability
- Update Pipeline: Kafka stream from profile/job updates to Elasticsearch (near real-time)
- Autocomplete: Separate prefix index with edge n-grams for instant suggestions
6. Messaging System
Real-Time Messaging Requirements
- Delivery: Sub-100ms delivery for online users
- Read Receipts: Show when message is delivered and read
- Typing Indicators: Show when other user is typing
- Group Chats: Support multi-party conversations
- Message History: Persistent storage, searchable history
Architecture
Redis] end subgraph Storage MessageDB[(Cassandra
Messages)] Redis[(Redis
Online Users)] end User1 <-->|WebSocket| WS1 User2 <-->|WebSocket| WS2 WS1 --> MsgRouter WS2 --> MsgRouter MsgRouter --> MessageDB MsgRouter --> PresenceSvc PresenceSvc --> Redis MsgRouter -.->|Route to WS2| WS2
Message Flow
- User1 sends message via WebSocket to WS1
- WS1 forwards to Message Router
- Router checks Presence Service - is User2 online?
- If online: look up User2's WebSocket server (WS2) in Redis, push message
- If offline: store in push notification queue
- Persist message to Cassandra (partition key: conversationId, sort key: timestamp)
- Send delivery receipt back to User1
Cassandra Schema
CREATE TABLE messages (
conversation_id UUID,
message_id TIMEUUID,
sender_id UUID,
content TEXT,
created_at TIMESTAMP,
read_by SET,
PRIMARY KEY (conversation_id, message_id)
) WITH CLUSTERING ORDER BY (message_id DESC);
Read Receipts
- Delivered: Message persisted and pushed to recipient's device
- Read: Recipient opened chat and message is visible on screen
- Send lightweight ACK messages over WebSocket (don't persist every receipt)
- Update
read_byset in Cassandra periodically (batched writes)
7. Job Matching and Recommendations
Job Recommendation System
LinkedIn's "Jobs You May Be Interested In" uses collaborative filtering and skills matching.
Candidate-Job Matching Score
MatchScore = W1 * SkillMatch
+ W2 * LocationFit
+ W3 * ExperienceFit
+ W4 * SalaryFit
+ W5 * CompanyFit
// SkillMatch: Jaccard similarity between candidate skills and job requirements
// LocationFit: Distance from job location (or remote flag)
// ExperienceFit: Years of experience vs required range
// SalaryFit: Candidate's expected salary vs job salary
// CompanyFit: Interest in company size, industry
Skills Graph
Build a skills ontology to understand skill relationships:
- Hierarchical: "Machine Learning" parent of "Deep Learning", "NLP"
- Related: "Java" related to "Spring Boot", "Hibernate"
- Alternative: "JavaScript" alternative to "TypeScript"
Application Tracking
- Applicant Tracking System (ATS): Track applications per job
- Application States: Applied → Reviewed → Interview → Offer → Hired/Rejected
- Notifications: Notify candidates of status changes
- Analytics: Time-to-hire, conversion rates per stage
Recruiter Tools
- Candidate Search: Advanced filters (skills, location, years of experience)
- InMail: Direct messaging to candidates (paid feature)
- Pipeline Management: Track candidates across multiple jobs
8. Scalability and Performance
Graph Database Sharding
- Challenge: Billion-node graph cannot fit on one machine
- Solution: Shard by userId ranges or geography
- Cross-Shard Queries: For PYMK (2nd degree), query across shards and merge results
- Hot Nodes: Replicate influencer nodes to multiple shards
Feed Cache Strategy
- Redis Sorted Sets: Key =
feed:{userId}, Score = timestamp or ranking score - Cache Size: Top 1000 posts per user (~500KB per user)
- Eviction: TTL-based (7 days) + LRU for inactive users
- Cache Invalidation: On new post, fanout to connections' cached feeds
Search Cluster Scaling
- Horizontal Sharding: Partition index by userId hash or geography
- Read Replicas: 3-5 replicas per shard for read-heavy traffic
- Index Updates: Near real-time via Kafka → Logstash → Elasticsearch pipeline
- Query Optimization: Use filters before scoring, cache frequent queries
CDN and Media Storage
- Profile Photos: Store in S3, serve via CDN (CloudFront)
- Video Content: Transcode to multiple resolutions, adaptive bitrate streaming
- Image Optimization: WebP format, responsive sizes (thumbnail, medium, full)
Database Choices
| Data Type | Database | Reason |
|---|---|---|
| Profiles | MySQL/PostgreSQL | Structured, ACID transactions |
| Connections | Neo4j/JanusGraph | Graph queries (PYMK, degrees) |
| Messages | Cassandra | High write throughput, time-series |
| Feed Cache | Redis | Sub-ms latency, sorted sets |
| Jobs | PostgreSQL | Complex queries, ACID |
| Search | Elasticsearch | Full-text search, ranking |
Rate Limiting
- API Gateway: Token bucket algorithm (100 req/min per user)
- Per-Feature Limits: Connection requests (50/day), InMail (20/month for premium)
- Anti-Spam: Detect rapid connection requests, messaging bursts
Summary
Designing LinkedIn requires handling multiple complex subsystems:
- Connection Graph: Graph database for efficient multi-hop queries, PYMK recommendations
- Feed System: Hybrid push/pull model with engagement-based ranking
- Search: Elasticsearch with personalized ranking based on connections and relevance
- Messaging: WebSocket-based real-time communication with Cassandra persistence
- Job Matching: Skills graph and collaborative filtering for recommendations
Key scalability patterns: aggressive caching (Redis for feeds), specialized databases (graph DB for connections, Cassandra for messages), and horizontal sharding across all layers.