LinkedIn#
Problem statement (interviewer prompt)
Design LinkedIn: professional profiles, an asymmetric connection graph (1st/2nd/3rd degree), feed of posts + articles, people + job search, recommendations (PYMK, jobs you may like), and messaging. Handle 1B users with strong privacy controls.
flowchart LR
U([User])
P[Profile Service]
G[Connection Graph]
F[Feed]
S[People Search]
J[Jobs Service]
MSG[Messaging]
U --> P
U --> G
U --> F
U --> S
U --> J
U --> MSG
classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
class U client;
class P,G,F,S,J,MSG service;
flowchart TB
subgraph Clients
Web
Mobile
end
subgraph Edge
CDN
LB
GW[REST + GraphQL]
end
subgraph Profile
PSVC[Profile Service]
PDB[(Profiles - Espresso<br/>document store)]
SKILL[Skills / Endorsements]
end
subgraph Graph[Economic Graph]
CONN[Connection Service]
GDB[(Distributed Graph<br/>LiquidGraph)]
DEG[Degree / shortest path]
end
subgraph Search
PEO[People Search]
JOB[Jobs Search]
GAL[Galene / Lucene search]
QU[Query understanding]
end
subgraph Feed
HOMEFEED[Home Feed]
AGG([Aggregator])
RANK([ML Ranker])
CANDS([Candidate Gen<br/>followed + suggested])
end
subgraph Jobs
JOBS[Jobs Service]
JDB[(Jobs DB)]
REC([Job Recommendations])
ALERT[Job Alerts]
APPLY[Easy Apply / ATS]
end
subgraph Msg
INMAIL[InMail]
DM[Messaging Service]
WS[WebSocket gateway]
end
subgraph Async
KAFKA[[Kafka pipelines]]
SAMZA([Samza / Flink])
EMB([Embeddings - Pinot])
LAKE[(Data lake)]
end
subgraph ML
PYM[People You May Know - PYMK]
PYMW[People You May Work With]
NOTIF([Notifications Ranker])
ADS[Ads / Sponsored]
end
Clients --> CDN --> LB --> GW
GW --> Profile --> PDB
GW --> Graph --> GDB
GW --> Search --> GAL
GW --> Feed --> AGG --> CANDS
CANDS --> Graph
Feed --> RANK
GW --> Jobs --> JDB
GW --> Msg --> WS
Profile --> KAFKA
Graph --> KAFKA
Jobs --> KAFKA
KAFKA --> SAMZA --> EMB
EMB --> PYM
EMB --> JOBS
PYM --> CANDS
ADS --> RANK
classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
class WS edge;
class GW,PSVC,SKILL,CONN,DEG,PEO,JOB,GAL,QU,HOMEFEED,JOBS,APPLY,INMAIL,DM,PYM,PYMW,ADS service;
class PDB,GDB,JDB,LAKE datastore;
class KAFKA queue;
class AGG,RANK,CANDS,REC,SAMZA,EMB,NOTIF compute;
class ALERT obs;
Distinctive parts#
- Economic Graph: members, companies, skills, jobs as nodes. Used for PYMK, job match, talent insights.
- People You May Know (PYMK): ML-driven candidate gen using 2nd/3rd-degree contacts, school/company overlap, embeddings.
- Galene = LinkedIn's Lucene-based search platform (now superseded internally) with custom relevance for "name + headline + company" queries.
- Espresso = LinkedIn's distributed document store (Helix-managed, Avro schemas).
- Voldemort historically for KV; replaced by Espresso + Venice.
Messaging#
- InMail (one-off to non-connections, paid) vs Direct Messaging (connections).
- Same kind of WS + inbox queue as WhatsApp but simpler (no E2E).
Jobs#
- Index = job postings + filters (location, exp, remote).
- Recommendations combine collaborative + content (skills, profile embedding).
Trade-offs#
- Strongly typed graph unlocks rich features but ops complexity.
- Multi-DC writes for profile but mostly single-region for graph hot path.
- Privacy & compliance (GDPR, recruiter visibility) drive complex ACL.
Glossary & fundamentals#
Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.
| Tag | Concept | What it is | Page |
|---|---|---|---|
HLD |
CDN | edge caching for static assets | cdn |
HLD |
Pub/Sub & message brokers | topics, consumer groups, delivery semantics | pub-sub-pattern |
HLD |
Realtime protocols | WS / SSE / polling / gRPC streaming | realtime-protocols |
HLD |
Batch & stream processing | Lambda vs Kappa, watermarks, windows | batch-stream-processing |
LLD |
REST API design | verbs, statuses, pagination, errors | rest-api-design |
Quick reference#
Functional#
- Profile (work history, education, skills).
- Connection graph (1st/2nd/3rd degree).
- Feed of activity (posts, articles, reactions).
- People search, jobs search.
- Messaging + InMail.
- Notifications.
Non-functional#
- 1B users; ~300M MAU.
- p99 profile page < 300 ms.
- Multi-region active for reads.
Capacity#
- ~50B notifications/day at peak.
- Feed traffic: 100M+ DAU × 30 feed loads.
Schema highlights#
member(id, headline, location, skills[], experience[], education[])connections(a_id, b_id, status, since)posts(id, author, ts, body, media[], visibility)jobs(id, company_id, title, location, skills[], desc)- Bi-directional shards on connections (by
aand byb) for both-direction queries.
Trade-offs#
- Graph queries (2nd-degree) = expensive joins; use precomputed degree counts + traversal limits.
- Recommendation quality = key product differentiator; large investment in ML.
- Recruiter Search has different latency vs free search; separate index.
Refs#
- LinkedIn engineering blog (Espresso, Voldemort, Pinot, Helix, Kafka, Samza).
- Galene/Search papers.
- "LinkedIn's Economic Graph" talks.
- ByteByteGo "Design LinkedIn".
FAQ#
How is LinkedIn's connection graph different from Twitter's?#
LinkedIn connections are symmetric: both sides must accept. Follows can be asymmetric. The graph also exposes 1st, 2nd, and 3rd degree distance to power search and PYMK.
How does People You May Know work?#
PYMK is a recommendation pipeline that mines shared connections, schools, employers, and behavioral signals. Triangle closing on the graph is the dominant signal.
How does LinkedIn job search scale?#
Elasticsearch clusters index jobs by title, skills, location, and seniority. Queries fan out across shards and rank with a learned model that uses user profile features.
How is LinkedIn's feed different from Facebook's?#
It blends posts, articles, jobs, and recommendations with stronger emphasis on professional intent. Ranking favors employer pages, mutual connections, and dwell time.
How is privacy enforced in LinkedIn search?#
Profile visibility settings are checked at query time. Anonymous viewers, blocked users, and 3rd-degree limits are applied as filters before ranking returns results.