Skip to content

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 a and by b) 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.

Profile visibility settings are checked at query time. Anonymous viewers, blocked users, and 3rd-degree limits are applied as filters before ranking returns results.

Video walkthrough

Design LinkedIn: System Design Mock with Senior SWE @ Amazon : via Exponent