Last Updated: December 19, 2025
LinkedIn is a professional networking platform that allows individuals to create and maintain an online career profile, connect with other professionals, apply for jobs, and share industry-related content.
Software Engineer at Tech Company
Sarah Chen
Product Manager at Google
30m
Excited to share that I've just been promoted to Senior Product Manager! Thank you to everyone who has supported me on this journey.
Emma Thompson
UX Designer at Apple
2h
Just published my thoughts on the future of AI in UX design. Key takeaway: AI won't replace designers, but designers who use AI will replace those who don't.
David Park
Startup Founder & CEO
4h
After 3 years of building my startup, here are 5 lessons I wish I knew earlier: 1. Hire slow, fire fast 2. Your first idea is rarely your best 3. Cash flow > Revenue 4. Culture is everything 5. Take care of your mental health
Alex Kumar
Data Scientist at Amazon
Rachel Green
HR Director at Netflix
It also serves as a recruiting and branding platform for companies to post job openings, build their presence, and hire qualified candidates.
In this chapter, we will explore the low-level design of LinkedIn like system in detail.
Let's start by clarifying the requirements:
Before starting the design, it's important to ask thoughtful questions to uncover hidden assumptions and better define the scope of the system.
Here is an example of how a conversation between the candidate and the interviewer might unfold:
Candidate: Should the system allow users to create detailed professional profiles?
Interviewer: Yes, members should be able to add a summary, work experience, and educational background.
Candidate: Should members be able to connect with each other?
Interviewer: Yes, the system should allow one member to send a connection request to another. The receiver can accept or reject it.
Candidate: Can members post updates, and should these be shown in a personalized feed?
Interviewer: Yes, members can create posts. A member should see posts from their connections in their news feed.
Candidate: Should members be able to like or comment on a post?
Interviewer: Yes, and the post’s author should be notified of these interactions.
Candidate: Do we support any search functionality?
Interviewer: Yes. Members should be able to search for other members by name (case-insensitive substring match is enough for now).
Candidate: Should the system include messaging, endorsements, job applications, or premium features?
Interviewer: No, let’s keep it simple. Focus only on core features: profiles, connections, posting, feed, notifications, and search.
After gathering the details, we can summarize the key system requirements.
Core entities are the foundational building blocks of our system. We identify them by analyzing key nouns (e.g., user, profile, connection request, message, activity log) and actions (e.g., connect, search, update, message, log) from the functional requirements. These typically translate into classes, enums, or interfaces in an object-oriented design.
Let’s walk through the key features and extract the relevant entities.
This directly points to a Member as the central entity representing a user. Each Member has a Profile, which in turn is composed of smaller, distinct entities: Experience and Education. These classes encapsulate the professional and academic history of a member.
The relationship between two members is a key concept. This leads to a Connection entity, which models the request itself, including the sender, receiver, and its current state. To manage these states consistently, a ConnectionStatus enum (PENDING, ACCEPTED, etc.) is required. The logic for managing these connections is encapsulated in a ConnectionService.
This introduces the Post entity as a piece of user-generated content. A NewsFeed entity is needed to represent the collection of posts displayed to a member. The logic for generating this feed is handled by a NewsFeedService. To allow for different ways of organizing the feed, a FeedSortingStrategy interface is introduced.
Interactions on a Post are modeled as their own entities. This leads to Like and Comment classes, which are associated with a Post and capture who performed the action and when.
To handle alerts, a Notification entity is needed to encapsulate the message content and its type. A NotificationType enum (CONNECTION_REQUEST, POST_LIKE, etc.) standardizes the kinds of alerts. A NotificationService is responsible for dispatching these notifications.
This functionality is encapsulated within a SearchService, which operates on the collection of Member entities to find matches.
To manage the complexity of interactions between various services and data models, a LinkedInSystem class is introduced. It acts as a Facade and Singleton, providing a high-level API for all client operations.
Member: The central entity representing a user on the network. It holds a profile, and connections.Profile: Contains a member's professional summary, a list of Experience objects, and a list of Education objects.Experience & Education: Data classes that store details about a member's work history and academic background.Connection: Represents a connection request between two members, tracking its status (PENDING, ACCEPTED, etc.).Post: Represents a text-based update created by a member. It also acts as a Subject to notify its author of interactions.Like & Comment: Represent interactions that members can perform on a Post.NewsFeed: Represents a member's personalized feed, containing a collection of posts from their connections.Notification: An entity representing an alert sent to a member for events like connection requests or post interactions.Enums (ConnectionStatus, NotificationType): Define fixed sets of statuses and types to ensure consistency across the system.Services (ConnectionService, NewsFeedService, SearchService, NotificationService): Classes that encapsulate the core business logic and orchestrate interactions between the data entities.LinkedInSystem: A Facade and Singleton that provides a simplified, high-level API to the entire system, acting as the primary entry point.These core entities define the essential abstractions of the LinkedIn system and will guide the structure of your low-level design and class diagrams.
The system is composed of several types of classes, each with a distinct role.
ConnectionStatus: Defines the lifecycle states of a connection request (PENDING, ACCEPTED, REJECTED).NotificationType: Classifies the type of notification being sent (CONNECTION_REQUEST, POST_LIKE).Education, ExperienceSimple data classes that capture a member's academic and professional history.
ProfileA container class that aggregates a member's summary, experiences, and educations.
ConnectionRepresents a connection request between two members, tracking its status and timestamps.
Like, CommentData classes that model user interactions on a Post.
NotificationA data class representing a single notification message to be sent to a user.
MemberRepresents a user of the platform.
It is a central class that acts as a concrete Observer (implementing NotificationObserver) to receive notifications. Its complex creation is handled by a nested Builder. It holds its Profile, a set of connections, and a list of notifications.
PostRepresents a single post in the news feed.
It is a concrete Subject (extending Subject) that notifies its author when other members interact with it (by liking or commenting).
NewsFeedResponsible for displaying a collection of posts according to a given FeedSortingStrategy.
ConnectionService, NewsFeedService, NotificationService, SearchServiceThese are service-layer classes that encapsulate specific business logic. For instance, ConnectionService handles sending and accepting requests, while NewsFeedService manages creating posts and generating feeds for members.
LinkedInSystem (Singleton & Facade)The primary entry point for the entire application.
It orchestrates all the services and manages the main data stores (e.g., the map of all members). It provides a simplified interface to the client, hiding the complex interactions between the various components.
The relationships between classes define the system's structure and data flow.
Member "has-a" Profile. The Profile's lifecycle is managed by the Member.Profile "has-a" list of Experience and Education objects.LinkedInSystem "has-a" set of core services (ConnectionService, NewsFeedService, etc.) and manages the collection of all Members.Member is associated with a set of other Members as connections.Connection object links two Members.Post is associated with its author Member. Likes and Comments are also associated with the Member who created them.NewsFeed is associated with a FeedSortingStrategy to determine the display order.Post (Subject) is associated with its NotificationObservers (typically the author Member).Member implements the NotificationObserver interface.Post extends the abstract Subject class.ChronologicalSortStrategy implements the FeedSortingStrategy interface.LinkedInSystem (Facade) depends on its various service classes to execute user commands.ConnectionService depends on NotificationService to inform users of new requests.Member.Builder to construct new Member objects.Post depends on Notification to create update messages for its observers.The FeedSortingStrategy allows the algorithm for sorting the news feed to be encapsulated and made interchangeable. The system can easily support new sorting methods (e.g., by relevance, by engagement) by creating new strategy classes without altering the NewsFeed or NewsFeedService.
This pattern is fundamental for real-time notifications. A Post (Subject) notifies its author Member (Observer) whenever a new like or comment is added. This decouples the action (e.g., liking a post) from the notification logic.
The Member.Builder class is used for the step-by-step construction of a Member object. This pattern is ideal for objects with many optional parameters (like summary, experience, education), providing a fluent and readable API while ensuring the Member object is created in a valid state.
The LinkedInSystem class serves as a facade. It provides a simple, high-level API (sendConnectionRequest, createPost, viewNewsFeed) that hides the complex internal workflows involving multiple services, data models, and notifications.
LinkedInSystem is implemented as a singleton to ensure a single, globally accessible point of control for the entire application. This prevents state inconsistencies and centralizes the management of services and data.
Defines standard statuses for connection requests and notification types to maintain consistency across services.
1class ConnectionStatus(Enum):
2 PENDING = "PENDING"
3 ACCEPTED = "ACCEPTED"
4 REJECTED = "REJECTED"
5 WITHDRAWN = "WITHDRAWN"
6
7
8class NotificationType(Enum):
9 CONNECTION_REQUEST = "CONNECTION_REQUEST"
10 POST_LIKE = "POST_LIKE"
11 POST_COMMENT = "POST_COMMENT"Captures a member’s professional background. Supports dynamic updates and display functionality.
1class Education:
2 def __init__(self, school: str, degree: str, start_year: int, end_year: int):
3 self.school = school
4 self.degree = degree
5 self.start_year = start_year
6 self.end_year = end_year
7
8 def __str__(self) -> str:
9 return f"{self.degree}, {self.school} ({self.start_year} - {self.end_year})"
10
11
12class Experience:
13 def __init__(self, title: str, company: str, start_date: date, end_date: Optional[date]):
14 self.title = title
15 self.company = company
16 self.start_date = start_date
17 self.end_date = end_date
18
19 def __str__(self) -> str:
20 end_str = "Present" if self.end_date is None else str(self.end_date)
21 return f"{self.title} at {self.company} ({self.start_date} to {end_str})"
22
23
24class Profile:
25 def __init__(self):
26 self.summary: Optional[str] = None
27 self.experiences: List[Experience] = []
28 self.educations: List[Education] = []
29
30 def set_summary(self, summary: str) -> None:
31 self.summary = summary
32
33 def add_experience(self, experience: Experience) -> None:
34 self.experiences.append(experience)
35
36 def add_education(self, education: Education) -> None:
37 self.educations.append(education)
38
39 def display(self) -> None:
40 print(f" Summary: {self.summary if self.summary else 'N/A'}")
41
42 print(" Experience:")
43 if not self.experiences:
44 print(" - None")
45 else:
46 for exp in self.experiences:
47 print(f" - {exp}")
48
49 print(" Education:")
50 if not self.educations:
51 print(" - None")
52 else:
53 for edu in self.educations:
54 print(f" - {edu}")Represents a LinkedIn member. Supports profile creation via the Builder Pattern and acts as an observer for real-time notifications.
1class Member(NotificationObserver):
2 def __init__(self, member_id: str, name: str, email: str, profile: Profile):
3 self.id = member_id
4 self.name = name
5 self.email = email
6 self.profile = profile
7 self.connections: Set['Member'] = set()
8 self.notifications: List['Notification'] = []
9
10 def get_id(self) -> str:
11 return self.id
12
13 def get_name(self) -> str:
14 return self.name
15
16 def get_email(self) -> str:
17 return self.email
18
19 def get_connections(self) -> Set['Member']:
20 return self.connections
21
22 def get_profile(self) -> Profile:
23 return self.profile
24
25 def add_connection(self, member: 'Member') -> None:
26 self.connections.add(member)
27
28 def display_profile(self) -> None:
29 print(f"\n--- Profile for {self.name} ({self.email}) ---")
30 self.profile.display()
31 print(f" Connections: {len(self.connections)}")
32
33 def view_notifications(self) -> None:
34 print(f"\n--- Notifications for {self.name} ---")
35 unread_notifications = [n for n in self.notifications if not n.is_read()]
36
37 if not unread_notifications:
38 print(" No new notifications.")
39 return
40
41 for notification in unread_notifications:
42 print(f" - {notification.get_content()}")
43 notification.mark_as_read()
44
45 def update(self, notification: 'Notification') -> None:
46 self.notifications.append(notification)
47 print(f"Notification pushed to {self.name}: {notification.get_content()}")
48
49 class Builder:
50 def __init__(self, name: str, email: str):
51 self.id = str(uuid.uuid4())
52 self.name = name
53 self.email = email
54 self.profile = Profile()
55
56 def with_summary(self, summary: str) -> 'Member.Builder':
57 self.profile.set_summary(summary)
58 return self
59
60 def add_experience(self, experience: Experience) -> 'Member.Builder':
61 self.profile.add_experience(experience)
62 return self
63
64 def add_education(self, education: Education) -> 'Member.Builder':
65 self.profile.add_education(education)
66 return self
67
68 def build(self) -> 'Member':
69 return Member(self.id, self.name, self.email, self.profile)Models a connection request between members and tracks its lifecycle state.
1class Connection:
2 def __init__(self, from_member: Member, to_member: Member):
3 self.from_member = from_member
4 self.to_member = to_member
5 self.status = ConnectionStatus.PENDING
6 self.requested_at = datetime.now()
7 self.accepted_at: Optional[datetime] = None
8
9 def get_from_member(self) -> Member:
10 return self.from_member
11
12 def get_to_member(self) -> Member:
13 return self.to_member
14
15 def get_status(self) -> ConnectionStatus:
16 return self.status
17
18 def set_status(self, status: ConnectionStatus) -> None:
19 self.status = status
20 if status == ConnectionStatus.ACCEPTED:
21 self.accepted_at = datetime.now()Each post tracks likes and comments. Uses the Observer Pattern to notify the post’s author of new interactions.
1class Post(Subject):
2 def __init__(self, author: Member, content: str):
3 super().__init__()
4 self.id = str(uuid.uuid4())
5 self.author = author
6 self.content = content
7 self.created_at = datetime.now()
8 self.likes: List[Like] = []
9 self.comments: List[Comment] = []
10 self.add_observer(author)
11
12 def add_like(self, member: Member) -> None:
13 self.likes.append(Like(member))
14 notification_content = f"{member.get_name()} liked your post."
15 notification = Notification(self.author.get_id(), NotificationType.POST_LIKE, notification_content)
16 self.notify_observers(notification)
17
18 def add_comment(self, member: Member, text: str) -> None:
19 self.comments.append(Comment(member, text))
20 notification_content = f"{member.get_name()} commented on your post: \"{text}\""
21 notification = Notification(self.author.get_id(), NotificationType.POST_COMMENT, notification_content)
22 self.notify_observers(notification)
23
24 def get_id(self) -> str:
25 return self.id
26
27 def get_author(self) -> Member:
28 return self.author
29
30 def get_content(self) -> str:
31 return self.content
32
33 def get_created_at(self) -> datetime:
34 return self.created_at
35
36 def get_likes(self) -> List[Like]:
37 return self.likes
38
39 def get_comments(self) -> List[Comment]:
40 return self.comments
41
42class Like:
43 def __init__(self, member: Member):
44 self.member = member
45 self.created_at = datetime.now()
46
47 def get_member(self) -> Member:
48 return self.member
49
50class Comment:
51 def __init__(self, author: Member, text: str):
52 self.author = author
53 self.text = text
54 self.created_at = datetime.now()
55
56 def get_author(self) -> Member:
57 return self.author
58
59 def get_text(self) -> str:
60 return self.text1class NewsFeed:
2 def __init__(self, posts: List[Post]):
3 self.posts = posts
4
5 def display(self, strategy: FeedSortingStrategy) -> None:
6 sorted_posts = strategy.sort(self.posts)
7 if not sorted_posts:
8 print(" Your news feed is empty.")
9 return
10
11 for post in sorted_posts:
12 print("----------------------------------------")
13 print(f"Post by: {post.get_author().get_name()} (at {post.get_created_at().date()})")
14 print(f"Content: {post.get_content()}")
15 print(f"Likes: {len(post.get_likes())}, Comments: {len(post.get_comments())}")
16 print("----------------------------------------")Implements the Strategy Pattern to support multiple feed sorting strategies. Currently defaults to reverse chronological.
Defines a generic notification system using the Observer Pattern.
1class Notification:
2 def __init__(self, member_id: str, notification_type: NotificationType, content: str):
3 self.id = str(uuid.uuid4())
4 self.member_id = member_id
5 self.type = notification_type
6 self.content = content
7 self.created_at = datetime.now()
8 self._is_read = False
9
10 def get_content(self) -> str:
11 return self.content
12
13 def mark_as_read(self) -> None:
14 self._is_read = True
15
16 def is_read(self) -> bool:
17 return self._is_read1class NotificationObserver(ABC):
2 @abstractmethod
3 def update(self, notification: 'Notification') -> None:
4 pass
5
6class Subject:
7 def __init__(self):
8 self.observers: List[NotificationObserver] = []
9
10 def add_observer(self, observer: NotificationObserver) -> None:
11 self.observers.append(observer)
12
13 def remove_observer(self, observer: NotificationObserver) -> None:
14 if observer in self.observers:
15 self.observers.remove(observer)
16
17 def notify_observers(self, notification: 'Notification') -> None:
18 for observer in self.observers:
19 observer.update(notification)1class FeedSortingStrategy(ABC):
2 @abstractmethod
3 def sort(self, posts: List[Post]) -> List[Post]:
4 pass
5
6class ChronologicalSortStrategy(FeedSortingStrategy):
7 def sort(self, posts: List[Post]) -> List[Post]:
8 return sorted(posts, key=lambda post: post.get_created_at(), reverse=True)1class NotificationService:
2 def send_notification(self, member: Member, notification: Notification) -> None:
3 member.update(notification)1class ConnectionService:
2 def __init__(self, notification_service: NotificationService):
3 self.notification_service = notification_service
4 self.connection_requests: Dict[str, Connection] = {}
5 self.lock = threading.Lock()
6
7 def send_request(self, from_member: Member, to_member: Member) -> str:
8 connection = Connection(from_member, to_member)
9 request_id = str(uuid.uuid4())
10
11 with self.lock:
12 self.connection_requests[request_id] = connection
13
14 print(f"{from_member.get_name()} sent a connection request to {to_member.get_name()}.")
15
16 notification = Notification(
17 to_member.get_id(),
18 NotificationType.CONNECTION_REQUEST,
19 f"{from_member.get_name()} wants to connect with you. Request ID: {request_id}"
20 )
21 self.notification_service.send_notification(to_member, notification)
22
23 return request_id
24
25 def accept_request(self, request_id: str) -> None:
26 with self.lock:
27 request = self.connection_requests.get(request_id)
28
29 if request and request.get_status() == ConnectionStatus.PENDING:
30 request.set_status(ConnectionStatus.ACCEPTED)
31
32 from_member = request.get_from_member()
33 to_member = request.get_to_member()
34
35 from_member.add_connection(to_member)
36 to_member.add_connection(from_member)
37
38 print(f"{to_member.get_name()} accepted the connection request from {from_member.get_name()}.")
39 del self.connection_requests[request_id]
40 else:
41 print("Invalid or already handled request ID.")1class NewsFeedService:
2 def __init__(self):
3 self.all_posts: Dict[str, List[Post]] = defaultdict(list)
4 self.lock = threading.Lock()
5
6 def add_post(self, member: Member, post: Post) -> None:
7 with self.lock:
8 self.all_posts[member.get_id()].append(post)
9
10 def get_member_posts(self, member: Member) -> List[Post]:
11 return self.all_posts.get(member.get_id(), [])
12
13 def display_feed_for_member(self, member: Member, feed_sorting_strategy: FeedSortingStrategy) -> None:
14 feed_posts = []
15
16 for connection in member.get_connections():
17 connection_posts = self.all_posts.get(connection.get_id(), [])
18 feed_posts.extend(connection_posts)
19
20 news_feed = NewsFeed(feed_posts)
21 news_feed.display(feed_sorting_strategy)1class SearchService:
2 def __init__(self, members: Collection[Member]):
3 self.members = members
4
5 def search_by_name(self, name: str) -> List[Member]:
6 return [member for member in self.members if name.lower() in member.get_name().lower()]This class is a Singleton that provides a simplified, high-level API to the entire complex subsystem.
1class LinkedInSystem:
2 _instance: Optional['LinkedInSystem'] = None
3 _lock = threading.Lock()
4
5 def __new__(cls):
6 if cls._instance is None:
7 with cls._lock:
8 if cls._instance is None:
9 cls._instance = super().__new__(cls)
10 return cls._instance
11
12 def __init__(self):
13 if hasattr(self, 'initialized'):
14 return
15
16 self.members: Dict[str, Member] = {}
17 self.connection_service = ConnectionService(NotificationService())
18 self.news_feed_service = NewsFeedService()
19 self.search_service = SearchService(self.members.values())
20 self.initialized = True
21
22 @classmethod
23 def get_instance(cls) -> 'LinkedInSystem':
24 return cls()
25
26 def register_member(self, member: Member) -> None:
27 self.members[member.get_id()] = member
28 print(f"New member registered: {member.get_name()}")
29
30 def get_member(self, name: str) -> Optional[Member]:
31 for member in self.members.values():
32 if member.get_name() == name:
33 return member
34 return None
35
36 def send_connection_request(self, from_member: Member, to_member: Member) -> str:
37 return self.connection_service.send_request(from_member, to_member)
38
39 def accept_connection_request(self, request_id: str) -> None:
40 self.connection_service.accept_request(request_id)
41
42 def create_post(self, member_id: str, content: str) -> None:
43 author = self.members[member_id]
44 post = Post(author, content)
45 self.news_feed_service.add_post(author, post)
46 print(f"{author.get_name()} created a new post.")
47
48 def get_latest_post_by_member(self, member_id: str) -> Optional[Post]:
49 member_posts = self.news_feed_service.get_member_posts(self.members[member_id])
50 if not member_posts:
51 return None
52 return member_posts[-1]
53
54 def view_news_feed(self, member_id: str) -> None:
55 member = self.members[member_id]
56 print(f"\n--- News Feed for {member.get_name()} ---")
57 self.news_feed_service.display_feed_for_member(member, ChronologicalSortStrategy())
58
59 def search_member_by_name(self, name: str) -> List[Member]:
60 return self.search_service.search_by_name(name)The demo class validates the entire system by simulating interactions on the professional network.
1class LinkedInDemo:
2 @staticmethod
3 def main():
4 system = LinkedInSystem.get_instance()
5
6 # 1. Create Members using the Builder Pattern
7 print("--- 1. Member Registration ---")
8 alice = Member.Builder("Alice", "[email protected]") \
9 .with_summary("Senior Software Engineer with 10 years of experience.") \
10 .add_experience(Experience("Sr. Software Engineer", "Google", date(2018, 1, 1), None)) \
11 .add_experience(Experience("Software Engineer", "Microsoft", date(2014, 6, 1), date(2017, 12, 31))) \
12 .add_education(Education("Princeton University", "M.S. in Computer Science", 2012, 2014)) \
13 .build()
14
15 bob = Member.Builder("Bob", "[email protected]") \
16 .with_summary("Product Manager at Stripe.") \
17 .add_experience(Experience("Product Manager", "Stripe", date(2020, 2, 1), None)) \
18 .add_education(Education("MIT", "B.S. in Business Analytics", 2015, 2019)) \
19 .build()
20
21 charlie = Member.Builder("Charlie", "[email protected]").build()
22
23 system.register_member(alice)
24 system.register_member(bob)
25 system.register_member(charlie)
26
27 alice.display_profile()
28
29 # 2. Connection Management
30 print("\n--- 2. Connection Management ---")
31 # Alice sends requests to Bob and Charlie
32 request_id1 = system.send_connection_request(alice, bob)
33 request_id2 = system.send_connection_request(alice, charlie)
34
35 bob.view_notifications() # Bob sees Alice's request
36
37 print("\nBob accepts Alice's request.")
38 system.accept_connection_request(request_id1)
39 print("Alice and Bob are now connected.")
40
41 # 3. Posting and News Feed
42 print("\n--- 3. Posting & News Feed ---")
43 bob.display_profile() # Bob has 1 connection
44 system.create_post(bob.get_id(), "Excited to share we've launched our new feature! #productmanagement")
45
46 # Alice views her news feed. She should see Bob's post.
47 system.view_news_feed(alice.get_id())
48
49 # Charlie views his feed. It should be empty as he is not connected to anyone.
50 system.view_news_feed(charlie.get_id())
51
52 # 4. Interacting with a Post (Observer Pattern in action)
53 print("\n--- 4. Post Interaction & Notifications ---")
54 bobs_post = system.get_latest_post_by_member(bob.get_id())
55 if bobs_post:
56 bobs_post.add_like(alice)
57 bobs_post.add_comment(alice, "This looks amazing! Great work!")
58
59 # Bob checks his notifications. He should see a like and a comment from Alice.
60 bob.view_notifications()
61
62 # 5. Searching for Members
63 print("\n--- 5. Member Search ---")
64 search_results = system.search_member_by_name("ali")
65 print("Search results for 'ali':")
66 for member in search_results:
67 print(f" - {member.get_name()}")
68
69if __name__ == "__main__":
70 LinkedInDemo.main()Which entity is primarily used to capture a member’s professional history in a LinkedIn-like system?
No comments yet. Be the first to comment!