avatarNaina Chaturvedi

Summary

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

215445

Abstract

comments.append(comment) comments[comment_id] = comment <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"Comment added successfully"</span>), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"User or song not found"</span>), <span class="hljs-number">404</span>

<span class="hljs-comment"># Search API - Search for songs or albums based on a given query</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/search'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">search</span>(): query = request.args.get(<span class="hljs-string">'q'</span>) search_results = [] <span class="hljs-keyword">for</span> song <span class="hljs-keyword">in</span> songs.values(): <span class="hljs-keyword">if</span> query.lower() <span class="hljs-keyword">in</span> song.title.lower() <span class="hljs-keyword">or</span> query.lower() <span class="hljs-keyword">in</span> song.album.lower() <span class="hljs-keyword">or</span> query.lower() <span class="hljs-keyword">in</span> song.artist.lower(): search_results.append(song) <span class="hljs-keyword">return</span> jsonify(songs=search_results)

<span class="hljs-comment"># Playlist API - Get details of a specific playlist for a user</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/playlists/<int:playlist_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_playlist</span>(<span class="hljs-params">user_id, playlist_id</span>): user = users.get(user_id) playlist = playlists.get(playlist_id) <span class="hljs-keyword">if</span> user <span class="hljs-keyword">and</span> playlist <span class="hljs-keyword">in</span> user.playlists: <span class="hljs-keyword">return</span> jsonify(playlist=playlist.dict), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"User or playlist not found"</span>), <span class="hljs-number">404</span>

<span class="hljs-comment"># User Feed API - Get the user's personalized feed with recommended songs and playlists</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/feed'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_feed</span>(<span class="hljs-params">user_id</span>): user = users.get(user_id) <span class="hljs-keyword">if</span> user: feed = [] <span class="hljs-keyword">for</span> playlist <span class="hljs-keyword">in</span> user.playlists: feed.extend(playlist.songs) <span class="hljs-keyword">return</span> jsonify(feed=feed), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"User not found"</span>), <span class="hljs-number">404</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run(debug=<span class="hljs-literal">True</span>)</pre></div><h1 id="ac7e">API Design</h1><p id="14ff">User Management API:</p><ul><li>Endpoint: POST /users</li><li>Description: Create a new user account.</li><li>Request body: { “username”: “john123”, “password”: “password123”, “email”: “<a href="mailto:[email protected]">[email protected]</a>” }</li></ul><p id="73f3">Song Management API:</p><ul><li>Endpoint: POST /songs</li><li>Description: Add a new song to the music library.</li><li>Request body: { “title”: “Song Title”, “artist”: “Artist Name”, “album”: “Album Name”, “duration”: 240 }</li></ul><p id="d84a">Playlist Management API:</p><ul><li>Endpoint: POST /users/{userId}/playlists</li><li>Description: Create a new playlist for a specific user.</li><li>Request body: { “title”: “My Playlist”, “songs”: [ “songId1”, “songId2” ] }</li></ul><p id="b532">Like API:</p><ul><li>Endpoint: POST /users/{userId}/likes</li><li>Description: Like a specific song for a user.</li><li>Request body: { “songId”: “songId1” }</li></ul><p id="c4b8">Comment API:</p><ul><li>Endpoint: POST /users/{userId}/comments</li><li>Description: Add a comment on a specific song for a user.</li><li>Request body: { “songId”: “songId1”, “text”: “Great song!” }</li></ul><p id="1a10">Search API:</p><ul><li>Endpoint: GET /search?q={query}</li><li>Description: Search for songs or albums based on a given query.</li><li>Response: List of songs or albums matching the query.</li></ul><p id="9f17">Playlist API:</p><ul><li>Endpoint: GET /users/{userId}/playlists/{playlistId}</li><li>Description: Get details of a specific playlist for a user.</li><li>Response: Playlist information with associated songs.</li></ul><p id="6453">User Feed API:</p><ul><li>Endpoint: GET /users/{userId}/feed</li><li>Description: Get the user’s personalized feed with recommended songs and playlists.</li><li>Response: User’s feed containing recommended songs and playlists.</li></ul><div id="4b78"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify

app = Flask(name)

<span class="hljs-comment"># Data Storage</span> users = {} songs = {} playlists = {} likes = {} comments = {}

<span class="hljs-comment"># User Class</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, user_id, username, password, email</span>): self.user_id = user_id self.username = username self.password = password self.email = email self.playlists = []

<span class="hljs-comment"># Song Class</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Song</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, song_id, title, artist, album, duration</span>): self.song_id = song_id self.title = title self.artist = artist self.album = album self.duration = duration self.likes = [] self.comments = []

<span class="hljs-comment"># Playlist Class</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Playlist</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, playlist_id, title</span>): self.playlist_id = playlist_id self.title = title self.songs = []

<span class="hljs-comment"># User Management API - Create a new user account</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_user</span>(): data = request.get_json() user_id = <span class="hljs-built_in">len</span>(users) + <span class="hljs-number">1</span> username = data.get(<span class="hljs-string">'username'</span>) password = data.get(<span class="hljs-string">'password'</span>) email = data.get(<span class="hljs-string">'email'</span>) user = User(user_id, username, password, email) users[user_id] = user <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"User created successfully"</span>), <span class="hljs-number">201</span>

<span class="hljs-comment"># Song Management API - Add a new song to the music library</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/songs'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_song</span>(): data = request.get_json() song_id = <span class="hljs-built_in">len</span>(songs) + <span class="hljs-number">1</span> title = data.get(<span class="hljs-string">'title'</span>) artist = data.get(<span class="hljs-string">'artist'</span>) album = data.get(<span class="hljs-string">'album'</span>) duration = data.get(<span class="hljs-string">'duration'</span>) song = Song(song_id, title, artist, album, duration) songs[song_id] = song <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"Song added successfully"</span>), <span class="hljs-number">201</span>

<span class="hljs-comment"># Playlist Management API - Create a new playlist for a specific user</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/playlists'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_playlist</span>(<span class="hljs-params">user_id</span>): data = request.get_json() playlist_id = <span class="hljs-built_in">len</span>(playlists) + <span class="hljs-number">1</span> title = data.get(<span class="hljs-string">'title'</span>) playlist = Playlist(playlist_id, title) user = users.get(user_id) <span class="hljs-keyword">if</span> user: user.playlists.append(playlist) playlists[playlist_id] = playlist <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"Playlist created successfully"</span>), <span class="hljs-number">201</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"User not found"</span>), <span class="hljs-number">404</span>

<span class="hljs-comment"># Like API - Like a specific song for a user</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/likes'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">like_song</span>(<span class="hljs-params">user_id</span>): data = request.get_json() song_id = data.get(<span class="hljs-string">'song_id'</span>) user = users.get(user_id) song = songs.get(song_id) <span class="hljs-keyword">if</span> user <span class="hljs-keyword">and</span> song: song.likes.append(user) likes[(user_id, song_id)] = <span class="hljs-literal">True</span> <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"Song liked successfully"</span>), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"User or song not found"</span>), <span class="hljs-number">404</span>

<span class="hljs-comment"># Comment API - Add a comment on a specific song for a user</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/comments'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_comment</span>(<span class="hljs-params">user_id</span>): data = request.get_json() song_id = data.get(<span class="hljs-string">'song_id'</span>) text = data.get(<span class="hljs-string">'text'</span>) user = users.get(user_id) song = songs.get(song_id) <span class="hljs-keyword">if</span> user <span class="hljs-keyword">and</span> song: comment_id = <span class="hljs-built_in">len</span>(song.comments) + <span class="hljs-number">1</span> comment = { <span class="hljs-string">'comment_id'</span>: comment_id, <span class="hljs-string">'user_id'</span>: user_id, <span class="hljs-string">'song_id'</span>: song_id, <span class="hljs-string">'text'</span>: text } song.comments.append(comment) comments[comment_id] = comment <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"Comment added successfully"</span>), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"User or song not found"</span>), <span class="hljs-number">404</span>

<span class="hljs-comment"># Search API - Search for songs or albums based on a given query</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/search'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">search</span>(): query = request.args.get(<span class="hljs-string">'q'</span>) search_results = [] <span class="hljs-keyword">for</span> song <span class="hljs-keyword">in</span> songs.values(): <span class="hljs-keyword">if</span> query.lower() <span class="hljs-keyword">in</span> song.title.lower() <span class="hljs-keyword">or</span> query.lower() <span class="hljs-keyword">in</span> song.album.lower() <span class="hljs-keyword">or</span> query.lower() <span class="hljs-keyword">in</span> song.artist.lower(): search_results.append(song.dict) <span class="hljs-keyword">return</span> jsonify(songs=search_results)

<span class="hljs-comment"># Playlist API - Get details of a specific playlist for a user</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/playlists/<int:playlist_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_playlist</span>(<span class="hljs-params">user_id, playlist_id</span>): user = users.get(user_id) playlist = playlists.get(playlist_id) <span class="hljs-keyword">if</span> user <span class="hljs-keyword">and</span> playlist <span class="hljs-keyword">in</span> user.playlists: <span class="hljs-keyword">return</span> jsonify(playlist=playlist.dict), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"User or playlist not found"</span>), <span class="hljs-number">404</span>

<span class="hljs-comment"># User Feed API - Get the user's personalized feed with recommended songs and playlists</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/feed'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_feed</span>(<span class="hljs-params">user_id</span>): user = users.get(user_id) <span class="hljs-keyword">if</span> user: feed = [] <span class="hljs-keyword">for</span> playlist <span class="hljs-keyword">in</span> user.playlists: feed.extend(playlist.songs) <span class="hljs-keyword">return</span> jsonify(feed=feed), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify(message=<span class="hljs-string">"Usernot found"</span>), <span class="hljs-number">404</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run(debug=<span class="hljs-literal">True</span>)</pre></div><h1 id="56ca">Complete Detailed Design</h1><p id="ae2a"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="0c0b"><i>Subscribe to youtube channel :</i></p><div id="5e16" class="link-block"> <a href="https://www.youtube.com/@ignito5917/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div> </div> </div> </a> </div><h1 id="226d">System Design — CricHD</h1><p id="dd01">We will be discussing in depth -</p><ul><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>What is CricHD</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Important Features</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Scaling Requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Data Model — ER requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>High Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Basic Low Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>API Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Complete Detailed Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Code implementation</b></a></li></ul><figure id="3a30"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*HhRsbg3rsBy7xe9e.png"><figcaption>Pic credits : Pinterest</figcaption></figure><h1 id="036b">What is CricHD</h1><p id="9f65">Crichd is an online platform designed to provide cricket enthusiasts with seamless access to live cricket matches and related content. With Crichd, users can watch matches in real-time, access match highlights, view player statistics, and engage with a vibrant cricket community. The platform supports a wide range of devices, including desktops, smartphones, and smart TVs.</p><h1 id="9a5b">Important Features</h1><ul><li>Live Streaming: Crichd enables users to watch live cricket matches from various leagues and tournaments.</li><li>Match Highlights: Users can catch up on the most exciting moments of a match through curated highlights.</li><li>Player Statistics: Crichd offers comprehensive player profiles and statistics, allowing fans to track their favorite players’ performance.</li><li>Commentary and Analysis: Users can access live commentary and post-match analysis to gain deeper insights into the game.</li><li>Social Interaction: Crichd facilitates user engagement through chat forums, polls, and social media integration.</li><li>Personalization: The platform provides personalized recommendations based on user preferences and viewing history.</li></ul><h1 id="1252">Scaling Requirements — Capacity Estimation</h1><p id="4842">Let’s assume —</p><blockquote id="d43c"><p>Total number of users: 100 Million</p></blockquote><blockquote id="096e"><p>Daily active users (DAU): 20 Million</p></blockquote><blockquote id="1da1"><p>Number of videos watched by user/day: 2</p></blockquote><blockquote id="9fcd"><p>Total number of videos watched per day: 40 Million videos/day</p></blockquote><p id="d339">Since the system is read-heavy, let’s assume the read-to-write ratio to be 100:1.</p><p id="5f2f">Total number of videos uploaded/day = 1/100 * 40 Million = 400,000 videos/day</p><p id="de7a"><b><i>Storage Estimation: Let’s assume the average size of each video is 100 MB.</i></b></p><p id="bf17"><b><i>Total Storage per day: 400,000 * 100 MB = 40 TB/day</i></b></p><p id="b49c"><b><i>For the next 3 years, the estimated storage will be: 40 TB * 365 days * 3 years = 43,800 TB = 43.8 PB</i></b></p><p id="661b"><b><i>Requests per second: 40 Million / 3600 seconds * 24 hours = 11.1K/second</i></b></p><blockquote id="9e5b"><p>To ensure a smooth and responsive user experience, Crichd needs to handle a large number of concurrent users during peak times, such as major cricket tournaments. The system must be capable of scaling horizontally by adding more servers and load balancers to distribute the incoming traffic efficiently. Additionally, a robust content delivery network (CDN) should be employed to reduce latency and improve streaming performance across different geographical regions.</p></blockquote><h1 id="09fe">Data Model — ER requirements</h1><p id="bc1d">Users:</p><ul><li>Fields:</li><li>User_id: Int (Primary Key)</li><li>Username: String</li><li>Email: String</li><li>Password: String</li></ul><p id="259b">Matches:</p><ul><li>Fields:</li><li>Match_id: Int (Primary Key)</li><li>Team1: String</li><li>Team2: String</li><li>Venue: String</li><li>Date: Date</li><li>Status: String</li></ul><p id="a81c">Videos:</p><ul><li>Fields:</li><li>Video_id: Int (Primary Key)</li><li>Match_id: Int (Foreign Key to Matches.Match_id)</li><li>Video_url: String</li><li>Caption: String</li><li>Timestamp: DateTime</li></ul><p id="ce63">Likes:</p><ul><li>Fields:</li><li>Like_id: Int (Primary Key)</li><li>User_id: Int (Foreign Key to Users.User_id)</li><li>Video_id: Int (Foreign Key to Videos.Video_id)</li><li>Timestamp: DateTime</li></ul><p id="f617">Comments:</p><ul><li>Fields:</li><li>Comment_id: Int (Primary Key)</li><li>User_id: Int (Foreign Key to Users.User_id)</li><li>Video_id: Int (Foreign Key to Videos.Video_id)</li><li>Caption_text: String</li><li>Timestamp: DateTime</li></ul><h1 id="5a5b">High Level Design</h1><p id="e6a5">Assumptions:</p><ul><li>There will be more reads than writes, so the system should be designed to handle read-heavy traffic.</li><li>Scalability is essential, and the system should be able to handle a large number of concurrent users.</li><li>Availability and reliability are crucial for providing a seamless streaming experience.</li><li>Latency should be minimized to ensure smooth video playback.</li></ul><h1 id="c801">Main Components and Services:</h1><p id="e069">Mobile/Web Clients:</p><ul><li>These are the users accessing the Crichd streaming service through mobile or web applications.</li></ul><p id="f3ad">Application Servers:</p><ul><li>Responsible for handling read and write operations.</li><li>Serve requests from the clients, process business logic, and interact with the database.</li><li>Perform operations such as video streaming, likes, comments, and user authentication.</li></ul><p id="2211">Load Balancer:</p><ul><li>Routes and distributes incoming requests from clients to multiple application servers to ensure scalability and high availability.</li><li>Helps distribute the load evenly and handle traffic spikes effectively.</li></ul><p id="5819">Cache (e.g., Memcache, Redis):</p><ul><li>Used to cache frequently accessed data to improve performance and reduce load on the database.</li><li>Caches user profiles, video metadata, and other frequently requested data to minimize database queries.</li></ul><p id="e23a">Content Delivery Network (CDN):</p><ul><li>Distributes video content to various geographical locations, reducing latency and improving streaming performance.</li><li>Caches video files at edge servers strategically placed near the users’ locations for faster content delivery.</li></ul><p id="220c">Database:</p><ul><li>Stores user data, match details, video metadata, likes, comments, and other relevant information.</li><li>Utilizes NoSQL databases (e.g., MongoDB, Cassandra) for flexibility and scalability.</li><li>Ensures high reliability and availability to maintain data integrity.</li></ul><h1 id="f320">Services:</h1><p id="2c64">Video Streaming Service:</p><ul><li>Handles the streaming of live cricket matches and recorded videos.</li><li>Retrieves video files from storage or CDN and delivers them to the clients for playback.</li><li>Supports adaptive streaming to adjust video quality based on the user’s network conditions.</li></ul><p id="9703">Like Service:</p><ul><li>Manages user likes for videos.</li><li>Provides the ability for users to like a specific video.</li><li>Stores the relationship between users and videos they have liked.</li></ul><p id="316d">Comment Service:</p><ul><li>Manages user comments on videos.</li><li>Enables users to post comments and replies on videos.</li><li>Stores the relationship between users, videos, and their associated comments.</li></ul><p id="e64c">User Authentication Service:</p><ul><li>Handles user authentication and authorization.</li><li>Verifies user credentials and provides access tokens or sessions for authenticated users.</li><li>Ensures secure access to user-specific functionalities.</li></ul><p id="bf3e">Recommendation Service:</p><ul><li>Provides personalized recommendations to users based on their preferences and viewing history.</li><li>Utilizes machine learning algorithms to analyze user behavior and suggest relevant videos or matches.</li></ul><p id="ea85">Feed Generation Service:</p><ul><li>Generates personalized feeds for users based on the videos they follow and interact with.</li><li>Aggregates video content, applies ranking algorithms, and presents a curated feed to each user.</li><li>Supports functionalities like displaying recent, popular, and relevant videos in the user’s feed.</li></ul><div id="3236"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, jsonify, request

app = Flask(name)

<span class="hljs-comment"># Sample data</span> users = { <span class="hljs-string">"user1"</span>: {<span class="hljs-string">"username"</span>: <span class="hljs-string">"John"</span>, <span class="hljs-string">"email"</span>: <span class="hljs-string">"[email protected]"</span>}, <span class="hljs-string">"user2"</span>: {<span class="hljs-string">"username"</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-string">"email"</span>: <span class="hljs-string">"[email protected]"</span>} }

matches = { <span class="hljs-string">"match1"</span>: {<span class="hljs-string">"team1"</span>: <span class="hljs-string">"Team A"</span>, <span class="hljs-string">"team2"</span>: <span class="hljs-string">"Team B"</span>, <span class="hljs-string">"venue"</span>: <span class="hljs-string">"Stadium X"</span>}, <span class="hljs-string">"match2"</span>: {<span class="hljs-string">"team1"</span>: <span class="hljs-string">"Team C"</span>, <span class="hljs-string">"team2"</span>: <span class="hljs-string">"Team D"</span>, <span class="hljs-string">"venue"</span>: <span class="hljs-string">"Stadium Y"</span>} }

<span class="hljs-comment"># User API endpoints</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/users/<user_id>"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user</span>(<span class="hljs-params">user_id</span>): <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">in</span> users: user = users[user_id] <span class="hljs-keyword">return</span> jsonify(user), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"User not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/users"</span>, methods=[<span class="hljs-string">"POST"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_user</span>(): data = request.get_json() user_id = data.get(<span class="hljs-string">"user_id"</span>) username = data.get(<span class="hljs-string">"username"</span>) email = data.get(<span class="hljs-string">"email"</span>) user = {<span class="hljs-string">"username"</span>: username, <span class="hljs-string">"email"</span>: email} users[user_id] = user <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"User created successfully"</span>}), <span class="hljs-number">201</span>

<span class="hljs-comment"># Match API endpoints</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/matches/<match_id>"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_match</span>(<span class="hljs-params">match_id</span>): <span class="hljs-keyword">if</span> match_id <span class="hljs-keyword">in</span> matches: <span class="hljs-keyword">match</span> = matches[match_id] <span class="hljs-keyword">return</span> jsonify(<span class="hljs-keyword">match</span>), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Match not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Live Streaming Service</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/matches/<match_id>/stream"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">live_stream</span>(<span class="hljs-params">match_id</span>): <span class="hljs-keyword">if</span> match_id <span class="hljs-keyword">in</span> matches: <span class="hljs-comment"># Code for live streaming logic</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Live streaming for match {} is available"</span>.<span class="hljs-built_in">format</span>(match_id)}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Match not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Match Highlights Service</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/matches/<match_id>/highlights"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">match_highlights</span>(<span class="hljs-params">match_id</span>): <span class="hljs-keyword">if</span> match_id <span class="hljs-keyword">in</span> matches: <span class="hljs-comment"># Code for retrieving match highlights</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Match highlights for match {} are available"</span>.<span class="hljs-built_in">format</span>(match_id)}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Match not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Player Statistics Service</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/matches/<match_id>/players/<player_id>/stats"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">player_stats</span>(<span class="hljs-params">match_id, player_id</span>): <span class="hljs-keyword">if</span> match_id <span class="hljs-keyword">in</span> matches: <span class="hljs-comment"># Code for retrieving player statistics</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Player statistics for player {} in match {} are available"</span>.<span class="hljs-built_in">format</span>(player_id, match_id)}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Match not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Commentary and Analysis Service</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/matches/<match_id>/commentary"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">commentary</span>(<span class="hljs-params">match_id</span>): <span class="hljs-keyword">if</span> match_id <span class="hljs-keyword">in</span> matches: <span class="hljs-comment"># Code for retrieving live commentary and analysis</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Commentary and analysis for match {} are available"</span>.<span class="hljs-built_in">format</span>(match_id)}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Match not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Social Interaction Service</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/matches/<match_id>/interactions"</span>, methods=[<span class="hljs-string">"POST"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">social_interaction</span>(<span class="hljs-params">match_id</span>): <span class="hljs-keyword">if</span> match_id <span class="hljs-keyword">in</span> matches: data = request.get_json() interaction_type = data.get(<span class="hljs-string">"type"</span>) <span class="hljs-comment"># Code for handling different types of social interactions (chat forums, polls, social media integration)</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Social interaction ({}) for match {} has been recorded"</span>.<span class="hljs-built_in">format</span>(interaction_type, match_id)}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Match not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">"main"</span>: app.run()</pre></div><blockquote id="1760"><p>User Interface: A responsive and intuitive web application interface to provide access to Crichd’s features.</p></blockquote><blockquote id="a9ee"><p>Authentication and Authorization: A secure authentication system to verify user credentials and manage access control.</p></blockquote><blockquote id="bc07"><p>Content Management System: A robust CMS to handle content ingestion, storage, and metadata management.</p></blockquote><blockquote id="8405"><p>Streaming Infrastructure: A scalable and reliable streaming infrastructure utilizing CDNs for efficient content delivery.</p></blockquote><blockquote id="6e20"><p>Recommendation Engine: A recommendation system that utilizes machine learning algorithms to personalize user recommendations based on their preferences and behavior.</p></blockquote><blockquote id="7a81"><p>Analytics and Monitoring: Tools and services to monitor system performance, track user behavior, and generate insights for further improvements.</p></blockquote><h1 id="5d88">Basic Low Level Design</h1><ul><li><code>GET /users/<user_id></code>: Retrieves user information based on the user ID.</li><li><code>POST /users</code>: Creates a new user.</li><li><code>GET /matches/<match_id></code>: Retrieves match information based on the match ID.</li><li><code>GET /videos/<video_id></code>: Retrieves video information based on the video ID.</li><li><code>GET /likes/<like_id></code>: Retrieves like information based on the like ID.</li><li><code>GET /comments/<comment_id></code>: Retrieves comment information based on the comment ID.</li></ul><div id="c3f0"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, user_id, username, password</span>): self.user_id = user_id self.username = username self.password = password <span class="hljs-comment"># Other user attributes</span>

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Match</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, match_id, team1, team2, venue, date, status</span>): self.match_id = match_id self.team1 = team1 self.team2 = team2 self.venue = venue self.date = date self.status = status <span class="hljs-comment"># Other match attributes</span>

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Video</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, video_id, match_id, video_url, caption, timestamp</span>): self.video_id = video_id self.match_id = match_id self.video_url = video_url self.caption = caption self.timestamp = timestamp <span class="hljs-comment"># Other video attributes</span>

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Like</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, like_id, user_id, video_id, timestamp</span>): self.like_id = like_id self.user_id = user_id self.video_id = video_id self.timestamp = timestamp <span class="hljs-comment"># Other like attributes</span>

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Comment</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, comment_id, user_id, video_id, caption_text, timestamp</span>): self.comment_id = comment_id self.user_id = user_id self.video_id = video_id self.caption_text = caption_text self.timestamp = timestamp <span class="hljs-comment"># Other comment attributes</span></pre></div><p id="04bd">User Management API:</p><ul><li>Create User: This API allows creating a new user in the system.</li><li>Endpoint: <code>POST /users</code></li><li>Request Body: <code>{ "username": "john", "email": "[email protected]", "password": "password" }</code></li><li>Response: <code>{ "message": "User created successfully" }</code></li></ul><p id="e121">Get User: This API retrieves user information based on the user ID.</p><ul><li>Endpoint: <code>GET /users/{user_id}</code></li><li>Response: User object</li></ul><p id="70c3">Update User: This API updates user information based on the user ID.</p><ul><li>Endpoint: <code>PATCH /users/{user_id}</code></li><li>Request Body: <code>{ "username": "john_doe" }</code></li><li>Response: <code>{ "message": "User updated successfully" }</code></li></ul><p id="a7fb">Match API:</p><ul><li>Get Match: This API retrieves match information based on the match ID.</li><li>Endpoint: <code>GET /matches/{match_id}</code></li><li>Response: Match object</li><li>Get Match Videos: This API retrieves videos related to a specific match.</li><li>Endpoint: <code>GET /matches/{match_id}/videos</code></li><li>Response: List of Video objects</li></ul><p id="29b9">Video API:</p><ul><li>Get Video: This API retrieves video information based on the video ID.</li><li>Endpoint: <code>GET /videos/{video_id}</code></li><li>Response: Video object</li></ul><p id="2621">Like Video: This API allows a user to like a video.</p><ul><li>Endpoint: <code>POST /videos/{video_id}/like</code></li><li>Request Body: <code>{ "user_id": "user1" }</code></li><li>Response: <code>{ "message": "Video liked successfully" }</code></li></ul><p id="f4a4">Comment on Video: This API allows a user to comment on a video.</p><ul><li>Endpoint: <code>POST /videos/{video_id}/comment</code></li><li>Request Body: <code>{ "user_id": "user1", "comment": "Great shot!" }</code></li><li>Response: <code>{ "message": "Comment added successfully" }</code></li></ul><p id="7791">Feed API:</p><ul><li>Get User Feed: This API retrieves a user’s personalized feed.</li><li>Endpoint: <code>GET /users/{user_id}/feed</code></li><li>Response: List of Video objects</li></ul><div id="a4a3"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, jsonify, request <span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

app = Flask(name)

<span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, user_id, username, password</span>): self.user_id = user_id self.username = username self.password = password

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Match</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, match_id, team1, team2, venue, date, status</span>): self.match_id = match_id self.team1 = team1 self.team2 = team2 self.venue = venue self.date = date self.status = status

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Video</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, video_id, match_id, video_url, caption, timestamp</span>): self.video_id = video_id self.match_id = match_id self.video_url = video_url self.caption = caption self.timestamp = timestamp

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Like</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, like_id, user_id, video_id, timestamp</span>): self.like_id = like_id self.user_id = user_id self.video_id = video_id self.timestamp = timestamp

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Comment</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, comment_id, user_id, video_id, caption_text, timestamp</span>): self.comment_id = comment_id self.user_id = user_id self.video_id = video_id self.caption_text = caption_text self.timestamp = timestamp

<span class="hljs-comment"># Sample data</span> users = { <span class="hljs-string">"user1"</span>: User(<span class="hljs-string">"user1"</span>, <span class="hljs-string">"John"</span>, <span class="hljs-string">"password1"</span>), <span class="hljs-string">"user2"</span>: User(<span class="hljs-string">"user2"</span>, <span class="hljs-string">"Alice"</span>, <span class="hljs-string">"password2"</span>) }

matches = { <span class="hljs-string">"match1"</span>: Match(<span class="hljs-string">"match1"</span>, <span class="hljs-string">"Team A"</span>, <span class="hljs-string">"Team B"</span>, <span class="hljs-string">"Stadium X"</span>, datetime.now(), <span class="hljs-string">"In Progress"</span>), <span class="hljs-string">"match2"</span>: Match(<span class="hljs-string">"match2"</span>, <span class="hljs-string">"Team C"</span>, <span class="hljs-string">"Team D"</span>, <span class="hljs-string">"Stadium Y"</span>, datetime.now(), <span class="hljs-string">"Upcoming"</span>) }

videos = { <span class="hljs-string">"video1"</span>: Video(<span class="hljs-string">"video1"</span>, <span class="hljs-string">"match1"</span>, <span class="hljs-string">"https://example.com/video1.mp4"</span>, <span class="hljs-string">"Great shot!"</span>, datetime.now()), <span class="hljs-string">"video2"</span>: Video(<span class="hljs-string">"video2"</span>, <span class="hljs-string">"match2"</span>, <span class="hljs-string">"https://example.com/video2.mp4"</span>, <span class="hljs-string">"Amazing goal!"</span>, datetime.now()) }

likes = { <span class="hljs-string">"like1"</span>: Like(<span class="hljs-string">"like1"</span>, <span class="hljs-string">"user1"</span>, <span class="hljs-string">"video1"</span>, datetime.now()), <span class="hljs-string">"like2"</span>: Like(<span class="hljs-string">"like2"</span>, <span class="hljs-string">"user2"</span>, <span class="hljs-string">"video1"</span>, datetime.now()) }

comments = { <span class="hljs-string">"comment1"</span>: Comment(<span class="hljs-string">"comment1"</span>, <span class="hljs-string">"user1"</span>, <span class="hljs-string">"video1"</span>, <span class="hljs-string">"Awesome!"</span>, datetime.now()), <span class="hljs-string">"comment2"</span>: Comment(<span class="hljs-string">"comment2"</span>, <span class="hljs-string">"user2"</span>, <span class="hljs-string">"video1"</span>, <span class="hljs-string">"Well played!"</span>, datetime.now()) }

<span class="hljs-comment"># User API endpoints</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/users/<user_id>"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user</span>(<span class="hljs-params">user_id</span>): <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">in</span> users: user = users[user_id] <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"user_id"</span>: user.user_id, <span class="hljs-string">"username"</span>: user.username}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"User not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/users"</span>, methods=[<span class="hljs-string">"POST"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_user</span>(): data = request.json user_id = data[<span class="hljs-string">"user_id"</span>] username = data[<span class="hljs-string">"username"</span>] password = data[<span class="hljs-string">"password"</span>] user = User(user_id, username, password) users[user_id] = user <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"User created successfully"</span>}), <span class="hljs-number">201</span>

<span class="hljs-comment"># Match API endpoints</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/matches/<match_id>"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_match</span>(<span class="hljs-params">match_id</span>): <span class="hljs-keyword">if</span> match_id <span class="hljs-keyword">in</span> matches: <span class="hljs-keyword">match</span> = matches[match_id] <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"match_id"</span>: <span class="hljs-keyword">match</span>.match_id, <span class="hljs-string">"team1"</span>: <span class="hljs-keyword">match</span>.team1, <span class="hljs-string">"team2"</span>: <span class="hljs-keyword">match</span>.team2}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Match not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Video API endpoints</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/videos/<video_id>"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_video</span>(<span class="hljs-params">video_id</span>): <span class="hljs-keyword">if</span> video_id <span class="hljs-keyword">in</span> videos: video = videos[video_id] <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"video_id"</span>: video.video_id, <span class="hljs-string">"match_id"</span>: video.match_id, <span class="hljs-string">"caption"</span>: video.caption}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Video not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Like API endpoints</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/likes/<like_id>"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_like</span>(<span class="hljs-params">like_id</span>): <span class="hljs-keyword">if</span> like_id <span class="hljs-keyword">in</span> likes: like = likes[like_id] <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"like_id"</span>: like.like_id, <span class="hljs-string">"user_id"</span>: like.user_id, <span class="hljs-string">"video_id"</span>: like.video_id}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Like not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Comment API endpoints</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/comments/<comment_id>"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_comment</span>(<span class="hljs-params">comment_id</span>): <span class="hljs-keyword">if</span> comment_id <span class="hljs-keyword">in</span> comments: comment = comments[comment_id] <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"comment_id"</span>: comment.comment_id, <span class="hljs-string">"user_id"</span>: comment.user_id, <span class="hljs-string">"video_id"</span>: comment.video_id}), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">"Comment not found"</span>}), <span class="hljs-number">404</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">"main"</span>: app.run()</pre></div><h1 id="a1d1">API Design</h1><p id="b51c">User Authentication API:</p><ul><li>Use Python’s Flask or Django framework to handle HTTP requests.</li><li>Implement functions for user login and registration, validating credentials, and generating access tokens or sessions.</li><li>Utilize authentication middleware to verify token/session validity before granting access to protected endpoints.</li></ul><p id="76a8">Match API:</p><ul><li>Implement a function to fetch a list of matches from the database and serialize the data into JSON format for the response.</li><li>Create a function to retrieve detailed information about a specific match based on the provided match_id.</li></ul><p id="ce4c">Player API:</p><ul><li>Develop functions to retrieve player information from the database and serialize the data into JSON format.</li><li>Implement a function to fetch details about a specific player based on the provided player_id.</li></ul><p id="ba3e">Streaming API:</p><ul><li>Integrate a third-party streaming service (e.g., YouTube Live) to obtain the streaming URL for a particular match.</li><li>Implement a function to fetch the streaming URL or details from the streaming service based on the provided match_id.</li></ul><p id="b717">Recommendation API:</p><ul><li>Utilize machine learning models or collaborative filtering algorithms to generate personalized recommendations for users.</li><li>Develop a function to retrieve recommended matches or players based on the user’s preferences and serialize the data into JSON format.</li></ul><div id="e814"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, jsonify, request

app = Flask(name)

<span class="hljs-comment"># User Authentication API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/auth/login'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">login</span>(): username = request.json.get(<span class="hljs-string">'username'</span>) password = request.json.get(<span class="hljs-string">'password'</span>) <span class="hljs-comment"># Implement login logic here</span> <span class="hljs-comment"># Verify username and password, generate token/session</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'token'</span>: <span class="hljs-string">'your_token_here'</span>})

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/auth/register'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">register</span>(): username = request.json.get(<span class="hljs-string">'username'</span>) password = request.json.get(<span class="hljs-string">'password'</span>) email = request.json.get(<span class="hljs-string">'email'</span>) <span class="hljs-comment"># Implement registration logic here</span> <span class="hljs-comment"># Create new user, store credentials in the database</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'User registered successfully'</span>})

<span class="hljs-comment"># Match API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/matches'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_matches</span>(): <span class="hljs-comment"># Fetch matches from the database</span> matches = [{<span class="hljs-string">'match_id'</span>: <span class="hljs-string">'1'</span>, <span class="hljs-string">'team1'</span>: <span class="hljs-string">'Team A'</span>, <span class="hljs-string">'team2'</span>: <span class="hljs-string">'Team B'</span>, <span class="hljs-string">'start_time'</span>: <span class="hljs-string">'2023-07-10'</span>, <span class="hljs-string">'end_time'</span>: <span class="hljs-string">'2023-07-12'</span>}, {<span class="hljs-string">'match_id'</span>: <span class="hljs-string">'2'</span>, <span class="hljs-string">'team1'</span>: <span class="hljs-string">'Team C'</span>, <span class="hljs-string">'team2'</span>: <span class="hljs-string">'Team D'</span>, <span class="hljs-string">'start_time'</span>: <span class="hljs-string">'2023-07-13'</span>, <span class="hljs-string">'end_time'</span>: <span class="hljs-string">'2023-07-15'</span>}] <span class="hljs-keyword">return</span> jsonify(matches)

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/matches/<match_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_match</span>(<span class="hljs-params">match_id</span>): <span class="hljs-comment"># Fetch match details from the database based on match_id</span> <span class="hljs-keyword">match</span> = {<span class="hljs-string">'match_id'</span>: match_id, <span class="hljs-string">'team1'</span>: <span class="hljs-string">'Team A'</span>, <span class="hljs-string">'team2'</span>: <span class="hljs-string">'Team B'</span>, <span class="hljs-string">'venue'</span>: <span class="hljs-string">'Stadium X'</span>, <span class="hljs-string">'date'</span>: <span class="hljs-string">'2023-07-10'</span>, <span class="hljs-string">'status'</span>: <span class="hljs-string">'Live'</span>} <span class="hljs-keyword">return</span> jsonify(<span class="hljs-keyword">match</span>)

<span class="hljs-comment"># Player API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/players'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_players</span>(): <span class="hljs-comment"># Fetch players from the database</span> players = [{<span class="hljs-string">'player_id'</span>: <span class="hljs-string">'1'</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Player A'</span>, <span class="hljs-string">'team'</span>: <span class="hljs-string">'Team A'</span>, <span class="hljs-string">'country'</span>: <span class="hljs-string">'Country X'</span>}, {<span class="hljs-string">'player_id'</span>: <span class="hljs-string">'2'</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Player B'</span>, <span class="hljs-string">'team'</span>: <span class="hljs-string">'Team B'</span>, <span class="hljs-string">'country'</span>: <span class="hljs-string">'Country Y'</span>}] <span class="hljs-keyword">return</span> jsonify(players)

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/players/<player_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_player</span>(<span class="hljs-params">player_id</span>): <span class="hljs-comment"># Fetch player details from the database based on player_id</span> player = {<span class="hljs-string">'player_id'</span>: player_id, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Player A'</span>, <span class="hljs-string">'age'</span>: <span class="hljs-number">28</span>, <span class="hljs-string">'batting_average'</span>: <span class="hljs-number">45.75</span>, <span class="hljs-string">'bowling_average'</span>: <span class="hljs-number">32.40</span>} <span class="hljs-keyword">return</span> jsonify(player)

<span class="hljs-comment"># Streaming API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/stream/<match_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_stream</span>(<span class="hljs-params">match_id</span>): <span class="hljs-comment"># Fetch streaming URL or details from the streaming service based on match_id</span> stream = {<span class="hljs-string">'stream_url'</span>: <span class="hljs-string">'your_stream_url_here'</span>} <span class="hljs-keyword">return</span> jsonify(stream)

<span class="hljs-comment"># Recommendation API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/recommendations/<user_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_recommendations</span>(<span class="hljs-params">user_id</span>): <span class="hljs-comment"># Fetch recommended matches or players for the user from the recommendation engine</span> recommendations = [{<span class="hljs-string">'match_id'</span>: <span class="hljs-string">'1'</span>, <span class="hljs-string">'team1'</span>: <span class="hljs-string">'Team A'</span>, <span class="hljs-string">'team2'</span>: <span class="hljs-string">'Team B'</span>}, {<span class="hljs-string">'match_id'</span>: <span class="hljs-string">'2'</span>, <span class="hljs-string">'team1'</span>: <span class="hljs-string">'Team C'</span>, <span class="hljs-string">'team2'</span>: <span class="hljs-string">'Team D'</span>}] <span class="hljs-keyword">return</span> jsonify(recommendations)

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()

</pre></div><h1 id="ef3e">Complete Detailed Design</h1><p id="e260"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="e408"><i>Subscribe to youtube channel :</i></p><div id="7cf7" class="link-block"> <a href="https://www.youtube.com/@ignito5917/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div> </div> </div> </a> </div><h1 id="01a7">Complete Code implementation</h1><p id="b241">Live Streaming:</p><div id="8526"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/live_stream/<int:match_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">live_stream</span>(<span class="hljs-params">match_id</span>): <span class="hljs-comment"># Retrieve live streaming URL or details based on match_id</span> streaming_url = get_streaming_url(match_id) <span class="hljs-keyword">if</span> streaming_url: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'stream_url'</span>: streaming_url}) <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Live streaming not available for this match'</span>})</pre></div><p id="3a80">Match Highlights:</p><div id="c637"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/match_highlights/<int:match_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">match_highlights</span>(<span class="hljs-params">match_id</span>): <span class="hljs-comment"># Retrieve curated match highlights based on match_id</span> highlights = get_match_highlights(match_id) <span class="hljs-keyword">if</span> highlights: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'highlights'</span>: highlights}) <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'No highlights available for this match'</span>})</pre></div><p id="bd2f">Player Statistics:</p><div id="f5be"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/player_stats/<int:player_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">player_stats</span>(<span class="hljs-params">player_id</span>): <span class="hljs-comment"># Retrieve player statistics based on player_id</span> stats = get_player_statistics(player_id) <span class="hljs-keyword">if</span> stats: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'player_stats'</span>: stats}) <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Player statistics not available'</span>})</pre></div><p id="2879">Commentary and Analysis:</p><div id="f90d"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/commentary/<int:match_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">commentary</span>(<span class="hljs-params">match_id</span>): <span class="hljs-comment"># Retrieve live commentary and analysis based on match_id</span> commentary_data = get_commentary(match_id) <span class="hljs-keyword">if</span> commentary_data: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'commentary'</span>: commentary_data}) <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Commentary and analysis not available for this match'</span>})</pre></div><p id="5dae">Social Interaction:</p><div id="bfb6"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/chat_forum'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">chat_forum</span>(): <span class="hljs-comment"># Retrieve chat forum messages</span> messages = get_chat_forum_messages() <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'messages'</span>: messages})</pre></div><div id="febe"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/api/polls'</span>, methods=[<span class="hljs-string">'GET'</span>]) <span class="hljs-keyword">def</span> <span class="hljs-title function_">polls</span>(): <span class="hljs-comment"># Retrieve available polls</span> polls_data = get_polls() <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'polls'</span>: polls_data})</pre></div><div id="5ee7"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/api/social_media_integration'</span>, methods=[<span class="hljs-string">'POST'</span>]) <span class="hljs-keyword">def</span> <span class="hljs-title function_">social_media_integration</span>(): <span class="hljs-comment"># Handle social media integration logic</span> <span class="hljs-comment"># Process social media posts, comments, etc.</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Social media integration successful'</span>})</pre></div><p id="ce0f">Personalization:</p><div id="515c"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/recommendations/<int:user_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">recommendations</span>(<span class="hljs-params">user_id</span>): <span class="hljs-comment"># Retrieve personalized recommendations for the user based on user_id</span> recommendations = get_personalized_recommendations(user_id) <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'recommendations'</span>: recommendations})</pre></div><h1 id="7e10">System Design — Alibaba</h1><p id="ec07">We will be discussing in depth -</p><ul><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>What is Alibaba</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Important Features</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Scaling Requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Data Model — ER requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>High Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Basic Low Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>API Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Complete Detailed Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Code implementation</b></a></li></ul><figure id="8a07"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*x9JtxzBx_7Mrs5Hj.png"><figcaption></figcaption></figure><h1 id="ba9c">What is Alibaba</h1><p id="3e00">Alibaba is a multinational conglomerate and one of the world’s largest e-commerce companies. It was founded in 1999 by Jack Ma and is headquartered in Hangzhou, China. Alibaba operates various online platforms that facilitate business-to-business, business-to-consumer, and consumer-to-consumer transactions. It provides a wide range of services including e-commerce, retail, cloud computing, digital media, and entertainment.</p><h1 id="dfbf">Important Features</h1><ul><li>E-commerce Platform: Alibaba offers a robust and user-friendly e-commerce platform where businesses and individuals can buy and sell products and services.</li><li>Payment Systems: Alibaba has developed secure and reliable payment systems, such as Alipay, to facilitate online transactions.</li><li>Logistics and Supply Chain Management: The company has built a comprehensive logistics network to ensure efficient delivery and management of goods.</li><li>Cloud Computing: Alibaba Cloud provides scalable and reliable cloud computing services, including storage, networking, and data analytics.</li><li>Artificial Intelligence: Alibaba utilizes AI technologies for various purposes, such as personalized recommendations, image recognition, and natural language processing.</li><li>Cross-border Trade: Alibaba enables international trade by connecting global buyers and suppliers through its platforms, such as Alibaba.com and AliExpress.</li></ul><h1 id="1f5a">Scaling Requirements — Capacity Estimation</h1><p id="095b">For the sake of simplicity, let’s consider the following scenario:</p><ul><li>Total number of users: 2 Billion</li><li>Daily active users (DAU): 500 million</li><li>Average number of products viewed by user/day: 5</li><li>Total number of products viewed per day: 2.5 Billion products/day</li><li>Read-to-write ratio: 100:1 (read-heavy system)</li><li>Total number of products uploaded/day: 1/100 * 2.5 Billion = 25 Million products/day</li></ul><p id="4243"><b><i>Storage Estimation:</i></b></p><ul><li><b><i>Average size of each product: 100 KB</i></b></li><li><b><i>Total storage per day: 25 Million * 100 KB = 2.5 TB/day</i></b></li><li><b><i>For the next 3 years: 2.5 TB * 5 * 365 = 4.56 PB</i></b></li></ul><p id="0ca6"><b><i>Requests per second:</i></b></p><ul><li><b><i>Number of read requests per second: 2.5 Billion / (3600 seconds * 24 hours) = 29.06K/sec</i></b></li></ul><blockquote id="7e34"><p>High Availability: The system should be designed to ensure maximum uptime and minimal service disruptions, even during peak traffic.</p></blockquote><blockquote id="8598"><p>Elasticity: The infrastructure should be scalable horizontally and vertically to handle varying load demands.</p></blockquote><blockquote id="97a1"><p>Distributed Architecture: The system should be distributed across multiple regions and data centers to improve performance, fault tolerance, and reduce latency.</p></blockquote><blockquote id="91bf"><p>Load Balancing: Load balancing techniques should be implemented to distribute incoming traffic evenly across multiple servers.</p></blockquote><blockquote id="d53b"><p>Caching: Caching mechanisms, such as content delivery networks (CDNs) and in-memory caches, should be employed to reduce latency and improve response times.</p></blockquote><blockquote id="1782"><p>Auto-scaling: Automated mechanisms should be in place to dynamically allocate resources based on demand, ensuring optimal resource utilization.</p></blockquote><h1 id="e80d">Data Model — ER requirements</h1><p id="1653">User:</p><ul><li>UserId: Int (Primary Key)</li><li>Username: String</li><li>Email: String</li><li>Password: String</li></ul><p id="9154">Product:</p><ul><li>ProductId: Int (Primary Key)</li><li>SellerId: Int (Foreign Key referencing User.UserId)</li><li>Name: String</li><li>Description: String</li><li>Price: Decimal</li><li>Inventory: Int</li></ul><p id="9373">Order:</p><ul><li>OrderId: Int (Primary Key)</li><li>UserId: Int (Foreign Key referencing User.UserId)</li><li>ProductId: Int (Foreign Key referencing Product.ProductId)</li><li>Quantity: Int</li><li>OrderDate: DateTime</li></ul><p id="e85d">Review:</p><ul><li>ReviewId: Int (Primary Key)</li><li>UserId: Int (Foreign Key referencing User.UserId)</li><li>ProductId: Int (Foreign Key referencing Product.ProductId)</li><li>Rating: Int</li><li>Comment: String</li><li>ReviewDate: DateTime</li></ul><h1 id="addc">High Level Design</h1><p id="3dc4">Assumptions:</p><ul><li>The system should handle a high volume of concurrent users.</li><li>The system should be horizontally scalable to accommodate increasing user demands.</li><li>Availability and reliability are crucial aspects of the system.</li><li>Caching and load balancing mechanisms should be implemented for performance optimization.</li><li>Security measures, such as encryption and authentication, need to be in place to protect user data.</li></ul><h1 id="8288">Main Components and Services:</h1><p id="d25d">User Management:</p><ul><li>User registration and authentication services.</li><li>User profile management (username, email, password).</li><li>User authorization and access control.</li></ul><p id="b5b4">Product Management:</p><ul><li>Product listing, creation, and modification services.</li><li>Inventory management and tracking.</li><li>Product search and filtering functionality.</li></ul><p id="ad24">Order Management:</p><ul><li>Order placement and processing services.</li><li>Order tracking and status updates.</li><li>Payment processing and integration with secure payment systems.</li></ul><p id="4db0">Reviews and Ratings:</p><ul><li>Review submission and management services.</li><li>Rating calculation and aggregation.</li><li>Integration with the product detail page to display reviews.</li></ul><p id="4446">Search and Recommendation:</p><ul><li>Search functionality to allow users to find products based on keywords, categories, and other attributes.</li><li>Recommendation engine to provide personalized product recommendations based on user preferences and behavior.</li></ul><p id="af5c">Caching and Load Balancing:</p><ul><li>Implement caching mechanisms to improve response times and reduce database load.</li><li>Utilize load balancers to distribute incoming traffic across multiple servers for better performance and fault tolerance.</li></ul><p id="087a">Security and Privacy:</p><ul><li>Implement encryption and secure communication protocols (e.g., HTTPS) to protect sensitive user data.</li><li>Ensure proper user authentication and authorization mechanisms to safeguard user accounts.</li><li>Apply data privacy measures and comply with relevant regulations (e.g., GDPR) to protect user privacy.</li></ul><div id="4178"><pre><span class="hljs-comment"># User Management Service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserManagementService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">register_user</span>(<span class="hljs-params">self, username, email, password</span>): <span class="hljs-comment"># Logic for user registration</span> user_id = generate_user_id() user = User(user_id, username, email, password) save_user_to_database(user) <span class="hljs-keyword">return</span> user_id

<span class="hljs-keyword">def</span> <span class="hljs-title function_">authenticate_user</span>(<span class="hljs-params">self, email, password</span>):
    <span class="hljs-comment"># Logic for user authentication</span>
    user = get_user_by_email(email)
    <span class="hljs-keyword">if</span> user <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">and</span> user.password == password:
        <span class="hljs-keyword">return</span> user.user_id
    <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">update_user_profile</span>(<span class="hljs-params">self, user_id, username, email, password</span>):
    <span class="hljs-comment"># Logic for updating user profile</span>
    user = get_user_by_id(user_id)
    <span class="hljs-keyword">if</span> user <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        user.username = username
        user.email = email
        user.password = password
        save_user_to_database(user)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>

<span class="hljs-comment"># Product Management Service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ProductManagementService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_product</span>(<span class="hljs-params">self, seller_id, name, description, price, inventory</span>): <span class="hljs-comment"># Logic for creating a new product</span> product_id = generate_product_id() product = Product(product_id, seller_id, name, description, price, inventory) save_product_to_database(product) <span class="hljs-keyword">return</span> product_id

<span class="hljs-keyword">def</span> <span class="hljs-title function_">update_product</span>(<span class="hljs-params">self, product_id, name, description, price, inventory</span>):
    <span class="hljs-comment"># Logic for updating product details</span>
    product = get_product_by_id(product_id)
    <span class="hljs-keyword">if</span> product <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        product.name = name
        product.description = description
        product.price = price
        product.inventory = inventory
        save_product_to_database(product)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">search_products</span>(<span class="hljs-params">self, keyword</span>):
    <span class="hljs-comment"># Logic for searching products based on a keyword</span>
    products = search_products_by_keyword(keyword)
    <span class="hljs-keyword">return</span> products

<span class="hljs-comment"># Order Management Service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">OrderManagementService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">place_order</span>(<span class="hljs-params">self, user_id, product_id, quantity</span>): <span class="hljs-comment"># Logic for placing an order</span> product = get_product_by_id(product_id) <span class="hljs-keyword">if</span> product <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">and</span> product.inventory >= quantity: order_id = generate_order_id() order = Order(order_id, user_id, product_id, quantity) save_order_to_database(order) reduce_product_inventory(product_id, quantity) <span class="hljs-keyword">return</span> order_id <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_order_status</span>(<span class="hljs-params">self, order_id</span>):
    <span class="hljs-comment"># Logic for getting the status of an order</span>
    order = get_order_by_id(order_id)
    <span class="hljs-keyword">if</span> order <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        <span class="hljs-keyword">return</span> order.status
    <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

<span class="hljs-comment"># Review and Rating Service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ReviewRatingService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">submit_review</span>(<span class="hljs-params">self, user_id, product_id, rating, comment</span>): <span class="hljs-comment"># Logic for submitting a review</span> review_id = generate_review_id() review = Review(review_id, user_id, product_id, rating, comment) save_review_to_database(review) <span class="hljs-keyword">return</span> review_id

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_product_reviews</span>(<span class="hljs-params">self, product_id</span>):
    <span class="hljs-comment"># Logic for retrieving reviews of a product</span>
    reviews = get_reviews_by_product_id(product_id)
    <span class="hljs-keyword">return</span> reviews

<span class="hljs-comment"># Example usage of the services</span> user_service = UserManagementService() product_service = ProductManagementService() order_service = OrderManagementService() review_service = ReviewRatingService()

<span class="hljs-comment"># User Management Service</span> user_id = user_service.register_user(<span class="hljs-string">"username"</span>, <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password"</span>) authenticated_user_id = user_service.authenticate_user(<span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password"</span>) user_service.update_user_profile(user_id, <span class="hljs-string">"new_username"</span>, <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"new_password"</span>)

<span class="hljs-comment"># Product Management Service</span> product_id = product_service.create_product(seller_id, <span class="hljs-string">"Product Name"</span>, <span class="hljs-string">"Product Description"</span>, <span class="hljs-number">9.99</span>, <span class="hljs-number">100</span>) product_service.update_product(product_id, <span class="hljs-string">"New Product Name"</span>, <span class="hljs-string">"New Product Description"</span>, <span class="hljs-number">19.99</span>, <span class="hljs-number">50</span>) search_results = product_service.search_products(<span class="hljs-string">"keyword"</span>)

<span class="hljs-comment"># Order Management Service</span> order_id = order_service.place_order(user_id, product_id, <span class="hljs-number">2</span>) order_status = order_service.get_order_status(order_id)

<span class="hljs-comment"># Review and Rating Service</span> review_id = review_service.submit_review(user_id, product_id, <span class="hljs-number">4</span>, <span class="hljs-string">"Great product!"</span>) product_reviews = review_service.get_product_reviews(product_id)</pre></div><blockquote id="5009"><p>Microservices Architecture: Alibaba’s system can be designed using a microservices architecture to ensure modularity, scalability, and fault isolation.</p></blockquote><blockquote id="b5d1"><p>Service Orchestration: A service orchestration layer can be implemented to coordinate communication and workflows between different microservices.</p></blockquote><blockquote id="5619"><p>Distributed Storage: Alibaba can leverage distributed storage systems, such as NoSQL databases or distributed file systems, to handle large volumes of data and provide high availability.</p></blockquote><blockquote id="85a8"><p>Message Queues: A message queue system can be used to decouple components and enable asynchronous processing of tasks.</p></blockquote><blockquote id="cca2"><p>Content Delivery Networks (CDNs): CDNs can be employed to cache and serve static content efficiently, reducing latency and network congestion.</p></blockquote><h1 id="f947">Basic Low Level Design</h1><div id="395c"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, user_id, username, password</span>): self.user_id = user_id self.username = username self.password = password <span class="hljs-comment"># other user attributes</span>

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Product</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, product_id, seller_id, name, price, inventory</span>): self.product_id = product_id self.seller_id = seller_id self.name = name self.price = price self.inventory = inventory <span class="hljs-comment"># other product attributes</span>

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Alibaba</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.users = {} self.products = []

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_user</span>(<span class="hljs-params">self, user</span>):
    self.users[user.user_id] = user

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_by_id</span>(<span class="hljs-params">self, user_id</span>):
    <span class="hljs-keyword">return</span> self.users.get(user_id)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">create_product</span>(<span class="hljs-params">self, seller_id, name, price, inventory</span>):
    product_id = <span class="hljs-built_in">len</span>(self.products) + <span class="hljs-number">1</span>
    product = Product(product_id, seller_id, name, price, inventory)
    self.products.append(product)

<span class="hljs-comment"># Additional methods for searching, purchasing, and managing products</span></pre></div><h1 id="40d9">API Design</h1><p id="7d44">User Management API:</p><ul><li>Endpoint: <code>/users</code></li><li>Methods: <code>POST</code></li><li>Description: This API allows users to create a new account.</li><li>Request Payload:</li><li><code>{ "username": "john_doe", "password": "password123" }</code></li><li>Response: HTTP status code indicating the success or failure of the account creation process.</li></ul><div id="efb7"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, request</pre></div><div id="be84"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(__name__)

<span class="hljs-attribute">alibaba</span> <span class="hljs-operator">=</span> Alibaba()</pre></div><div id="9641"><pre><span class="hljs-meta">@app</span>.route(<span class="hljs-string">"/users"</span>, methods=[<span class="hljs-string">"POST"</span>]) def create_user(): <span class="hljs-keyword">data</span> = request.get_json() user_id = len(alibaba.users) + <span class="hljs-number">1</span> user = User(user_id, <span class="hljs-keyword">data</span>[<span class="hljs-string">"username"</span>], <span class="hljs-keyword">data</span>[<span class="hljs-string">"password"</span>]) alibaba.add_user(user) <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User created successfully"</span>}, <span class="hljs-number">201</span></pre></div><p id="15c4">Product Management API:</p><ul><li>Endpoint: <code>/products</code></li><li>Methods: <code>POST</code></li><li>Description: This API allows sellers to create a new product listing.</li><li>Request Payload:</li><li><code>{ "seller_id": 1, "name": "Product A", "price": 9.99, "inventory": 100 }</code></li><li>Response: HTTP status code indicating the success or failure of the product creation process.</li></ul><div id="cd87"><pre><span class="hljs-meta">@app</span>.route(<span class="hljs-string">"/products"</span>, methods=[<span class="hljs-string">"POST"</span>]) def create_product(): <span class="hljs-keyword">data</span> = request.get_json() seller_id = <span class="hljs-keyword">data</span>[<span class="hljs-string">"seller_id"</span>] name = <span class="hljs-keyword">data</span>[<span class="hljs-string">"name"</span>] price = <span class="hljs-keyword">data</span>[<span class="hljs-string">"price"</span>] inventory = <span class="hljs-keyword">data</span>[<span class="hljs-string">"inventory"</span>] alibaba.create_product(seller_id, name, price, inventory) <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Product created successfully"</span>}, <span class="hljs-number">201</span></pre></div><p id="a788">Product Search API:</p><ul><li>Endpoint: <code>/products</code></li><li>Methods: <code>GET</code></li><li>Description: This API allows users to search for products based on various criteria.</li><li>Request Parameters:</li><li><code>query</code>: The search query entered by the user (optional).</li><li><code>category</code>: The category of products to filter the search results (optional).</li><li>Response: A list of products matching the search criteria.</li></ul><div id="0118"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/products"</span>, methods=[<span class="hljs-string">"GET"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">search_products</span>(): query = request.args.get(<span class="hljs-string">"query"</span>) category = request.args.get(<span class="hljs-string">"category"</span>) <span class="hljs-comment"># Perform product search based on query and category</span> <span class="hljs-comment"># Return the search results as a JSON response</span> <span class="hljs-keyword">return</span> {<span class="hljs-string">"results"</span>: search_results}</pre></div><p id="ee23">Product Purchase API:</p><ul><li>Endpoint: <code>/products/{product_id}/purchase</code></li><li>Methods: <code>POST</code></li><li>Description: This API allows users to purchase a specific product.</li><li>Request Parameters:</li><li><code>product_id</code>: The ID of the product to purchase.</li><li><code>user_id</code>: The ID of the user making the purchase.</li><li><code>quantity</code>: The quantity of the product to purchase.</li><li>Response: HTTP status code indicating the success or failure of the purchase process.</li></ul><div id="91d9"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">"/products/<int:product_id>/purchase"</span>, methods=[<span class="hljs-string">"POST"</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">purchase_product</span>(<span class="hljs-params">product_id</span>): data = request.get_json() user_id = data[<span class="hljs-string">"user_id"</span>] quantity = data[<span class="hljs-string">"quantity"</span>] <span class="hljs-comment"># Perform the purchase logic</span> <span class="hljs-comment"># Return the purchase status as a JSON response</span> <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Purchase successful"</span>}</pre></div><div id="1a70"><pre><span class="hljs-comment"># Import necessary libraries</span> <span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify

<span class="hljs-comment"># Create Flask application</span> app = Flask(name)

<span class="hljs-comment"># Define endpoint for product listing</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/products'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_product_list</span>(): <span class="hljs-comment"># Retrieve query parameters</span> category = request.args.get(<span class="hljs-string">'category'</span>) min_price = request.args.get(<span class="hljs-string">'min_price'</span>) max_price = request.args.get(<span class="hljs-string">'max_price'</span>)

<span class="hljs-comment"># Perform filtering based on query parameters (simplified example)</span>
filtered_products = filter_products(category, min_price, max_price)

<span class="hljs-comment"># Prepare response data</span>
response = {
    <span class="hljs-string">'status'</span>: <span class="hljs-string">'success'</span>,
    <span class="hljs-string">'data'</span>: filtered_products
}

<span class="hljs-comment"># Return JSON response</span>
<span class="hljs-keyword">return</span> jsonify(response), <span class="hljs-number">200</span>

<span class="hljs-comment"># Helper function for filtering products (simplified example)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">filter_products</span>(<span class="hljs-params">category, min_price, max_price</span>): <span class="hljs-comment"># Perform actual filtering based on provided parameters</span> <span class="hljs-comment"># (This function would typically interact with the database or data storage)</span>

<span class="hljs-comment"># Placeholder example with static data</span>
products = [
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Product 1'</span>, <span class="hljs-string">'price'</span>: <span class="hljs-number">100</span>, <span class="hljs-string">'category'</span>: <span class="hljs-string">'Electronics'</span>},
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Product 2'</span>, <span class="hljs-string">'price'</span>: <span class="hljs-number">50</span>, <span class="hljs-string">'category'</span>: <span class="hljs-string">'Clothing'</span>},
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">3</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Product 3'</span>, <span class="hljs-string">'price'</span>: <span class="hljs-number">200</span>, <span class="hljs-string">'category'</span>: <span class="hljs-string">'Electronics'</span>},
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">4</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Product 4'</span>, <span class="hljs-string">'price'</span>: <span class="hljs-number">150</span>, <span class="hljs-string">'category'</span>: <span class="hljs-string">'Home'</span>},
]

filtered_products = []
<span class="hljs-keyword">for</span> product <span class="hljs-keyword">in</span> products:
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">not</span> category <span class="hljs-keyword">or</span> product[<span class="hljs-string">'category'</span>] == category) <span class="hljs-keyword">and</span> \
            (<span class="hljs-keyword">not</span> min_price <span class="hljs-keyword">or</span> product[<span class="hljs-string">'price'</span>] &gt;= <span class="hljs-built_in">int</span>(min_price)) <span class="hljs-keyword">and</span> \
            (<span class="hljs-keyword">not</span> max_price <span class="hljs-keyword">or</span> product[<span class="hljs-string">'price'</span>] &lt;= <span class="hljs-built_in">int</span>(max_price)):
        filtered_products.append(product)

<span class="hljs-keyword">return</span> filtered_products

<span class="hljs-comment"># Run the Flask application</span> <span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()</pre></div><div id="2a53"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask <span class="hljs-keyword">from</span> flask_restful <span class="hljs-keyword">import</span> Api, Resource, reqparse

app = Flask(name) api = Api(app)

<span class="hljs-comment"># Define request parser for validation</span> product_parser = reqparse.RequestParser() product_parser.add_argument(<span class="hljs-string">'category'</span>, <span class="hljs-built_in">type</span>=<span class="hljs-built_in">str</span>) product_parser.add_argument(<span class="hljs-string">'min_price'</span>, <span class="hljs-built_in">type</span>=<span class="hljs-built_in">float</span>) product_parser.add_argument(<span class="hljs-string">'max_price'</span>, <span class="hljs-built_in">type</span>=<span class="hljs-built_in">float</span>)

<span class="hljs-comment"># Define the ProductList resource</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ProductList</span>(<span class="hljs-title class_ inherited__">Resource</span>): <span class="hljs-keyword">def</span> <span class="hljs-title function_">get</span>(<span class="hljs-params">self</span>): <span class="hljs-comment"># Parse and validate the request arguments</span> args = product_parser.parse_args()

    <span class="hljs-comment"># Perform filtering based on request arguments (simplified example)</span>
    filtered_products = filter_products(args[<span class="hljs-string">'category'</span>], args[<span class="hljs-string">'min_price'</span>], args[<span class="hljs-string">'max_price'</span>])

    <span class="hljs-comment"># Prepare response data</span>
    response = {
        <span class="hljs-string">'status'</span>: <span class="hljs-string">'success'</span>,
        <span class="hljs-string">'data'</span>: filtered_products
    }

    <span class="hljs-keyword">return</span> response, <span class="hljs-number">200</span>

<span class="hljs-comment"># Helper function for filtering products (simplified example)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">filter_products</span>(<span class="hljs-params">category, min_price, max_price</span>): <span class="hljs-comment"># Perform actual filtering based on provided parameters</span> <span class="hljs-comment"># (This function would typically interact with the database or data storage)</span>

<span class="hljs-comment"># Placeholder example with static data</span>
products = [
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Product 1'</span>, <span class="hljs-string">'price'</span>: <span class="hljs-number">100</span>, <span class="hljs-string">'category'</span>: <span class="hljs-string">'Electronics'</span>},
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Product 2'</span>, <span class="hljs-string">'price'</span>: <span class="hljs-number">50</span>, <span class="hljs-string">'category'</span>: <span class="hljs-string">'Clothing'</span>},
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">3</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Product 3'</span>, <span class="hljs-string">'price'</span>: <span class="hljs-number">200</span>, <span class="hljs-string">'category'</span>: <span class="hljs-string">'Electronics'</span>},
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">4</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Product 4'</span>, <span class="hljs-string">'price'</span>: <span class="hljs-number">150</span>, <span class="hljs-string">'category'</span>: <span class="hljs-string">'Home'</span>},
]

filtered_products = []
<span class="hljs-keyword">for</span> product <span class="hljs-keyword">in</span> products:
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">not</span> category <span class="hljs-keyword">or</span> product[<span class="hljs-string">'category'</span>] == category) <span class="hljs-keyword">and</span> \
            (<span class="hljs-keyword">not</span> min_price <span class="hljs-keyword">or</span> product[<span class="hljs-string">'price'</span>] &gt;= min_price) <span class="hljs-keyword">and</span> \
            (<span class="hljs-keyword">not</span> max_price <span class="hljs-keyword">or</span> product[<span class="hljs-string">'price'</span>] &lt;= max_price):
        filtered_products.append(product)

<span class="hljs-keyword">return</span> filtered_products

<span class="hljs-comment"># Add the ProductList resource to the API with its corresponding URL</span> api.add_resource(ProductList, <span class="hljs-string">'/products'</span>)

<span class="hljs-comment"># Run the Flask application</span> <span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()</pre></div><h1 id="2673">Complete Detailed Design</h1><p id="87da"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="51b2"><i>Subscribe to youtube channel :</i></p><div id="3fce" class="link-block"> <a href="https://www.youtube.com/@ignito5917/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div> </div> </div> </a> </div><h1 id="720a">Complete Code implementation</h1><p id="28f1">E-commerce Platform:</p><div id="e9b7"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">EcommercePlatform</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.products = []</pre></div><div id="92d1"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_product</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, product</span>): <span class="hljs-variable language_">self</span>.products.append(product)</pre></div><div id="3c0b"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">remove_product</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, product</span>): <span class="hljs-variable language_">self</span>.products.remove(product)</pre></div><div id="69a4"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_products</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.products</pre></div><div id="e207"><pre># Usage example: platform = <span class="hljs-built_in">EcommercePlatform</span>() platform.<span class="hljs-built_in">add_product</span>(<span class="hljs-string">"Product 1"</span>) platform.<span class="hljs-built_in">add_product</span>(<span class="hljs-string">"Product 2"</span>) <span class="hljs-built_in">print</span>(platform.<span class="hljs-built_in">get_products</span>()) platform.<span class="hljs-built_in">remove_product</span>(<span class="hljs-string">"Product 1"</span>) <span class="hljs-built_in">print</span>(platform.<span class="hljs-built_in">get_products</span>())</pre></div><p id="e4d9">Payment Systems:</p><div id="5c07"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">PaymentSystem</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.balance = <span class="hljs-number">0</span></pre></div><div id="9c69"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">deposit</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, amount</span>): <span class="hljs-variable language_">self</span>.balance += amount</pre></div><div id="b6cc"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">withdraw</span>(<span class="hljs-params">self, amount</span>): <span class="hljs-keyword">if</span> self.balance >= amount: self.balance -= amount <span class="hljs-keyword">else</span>: <span class="hljs-built_in">print</span>(<span class="hljs-string">"Insufficient balance"</span>)</pre></div><div id="dbee"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_balance</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.balance</pre></div><div id="f43f"><pre><span class="hljs-comment"># Usage example:</span> payment_<span class="hljs-params">system</span> = Payment<span class="hljs-params">System</span>() payment_<span class="hljs-params">system</span>.deposit(<span class="hljs-number">1000</span>) payment_<span class="hljs-params">system</span>.withdraw(<span class="hljs-number">500</span>) <span class="hljs-literal">print</span>(payment_<span class="hljs-params">system</span>.get_balance())</pre></div><p id="afcf">Logistics and Supply Chain Management:</p><div id="1e3f"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">LogisticsManager</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.packages = []</pre></div><div id="8456"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_package</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, package</span>): <span class="hljs-variable language_">self</span>.packages.append(package)</pre></div><div id="5c2e"><pre> def remove_package(<span class="hljs-built_in">self</span>, <span class="hljs-built_in">package</span>): <span class="hljs-built_in">self</span>.packages.<span class="hljs-built_in">remove</span>(<span class="hljs-built_in">package</span>)</pre></div><div id="02bd"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_packages</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.packages</pre></div><div id="ccc8"><pre># Usage example: logistics_manager = <span class="hljs-built_in">LogisticsManager</span>() logistics_manager.<span class="hljs-built_in">add_package</span>(<span class="hljs-string">"Package 1"</span>) logistics_manager.<span class="hljs-built_in">add_package</span>(<span class="hljs-string">"Package 2"</span>) <span class="hljs-built_in">print</span>(logistics_manager.<span class="hljs-built_in">get_packages</span>()) logistics_manager.<span class="hljs-built_in">remove_package</span>(<span class="hljs-string">"Package 1"</span>) <span class="hljs-built_in">print</span>(logistics_manager.<span class="hljs-built_in">get_packages</span>())</pre></div><p id="70e7">Cloud Computing:</p><div id="041f"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">CloudComputing</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.storage = [] <span class="hljs-variable language_">self</span>.networking = [] <span class="hljs-variable language_">self</span>.data_analytics = []</pre></div><div id="2b43"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_storage</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, storage</span>): <span class="hljs-variable language_">self</span>.storage.append(storage)</pre></div><div id="0aca"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_networking</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, networking</span>): <span class="hljs-variable language_">self</span>.networking.append(networking)</pre></div><div id="5f70"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_data_analytics</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, data_analytics</span>): <span class="hljs-variable language_">self</span>.data_analytics.append(data_analytics)</pre></div><div id="2f96"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_storage</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.storage</pre></div><div id="80b0"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_networking</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.networking</pre></div><div id="bb58"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_data_analytics</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.data_analytics</pre></div><div id="27af"><pre># Usage example: cloud_computing = <span class="hljs-built_in">CloudComputing</span>() cloud_computing.<span class="hljs-built_in">add_storage</span>(<span class="hljs-string">"Storage 1"</span>) cloud_computing.<span class="hljs-built_in">add_networking</span>(<span class="hljs-string">"Networking 1"</span>) cloud_computing.<span class="hljs-built_in">add_data_analytics</span>(<span class="hljs-string">"Data Analytics 1"</span>) <span class="hljs-built_in">print</span>(cloud_computing.<span class="hljs-built_in">get_storage</span>()) <span class="hljs-built_in">print</span>(cloud_computing.<span class="hljs-built_in">get_networking</span>()) <span class="hljs-built_in">print</span>(cloud_computing.<span class="hljs-built_in">get_data_analytics</span>())</pre></div><p id="cc81">Artificial Intelligence:</p><div id="7eea"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">ArtificialIntelligence</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.recommendations = [] <span class="hljs-variable language_">self</span>.image_recognition = [] <span class="hljs-variable language_">self</span>.nlp = []</pre></div><div id="fec6"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_recommendation</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, recommendation</span>): <span class="hljs-variable language_">self</span>.recommendations.append(recommendation)</pre></div><div id="e6a7"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_image_recognition</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, image_recognition</span>): <span class="hljs-variable language_">self</span>.image_recognition.append(image_recognition)</pre></div><div id="1f29"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_nlp</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, nlp</span>): <span class="hljs-variable language_">self</span>.nlp.append(nlp)</pre></div><div id="e96a"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_recommendations</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.recommendations</pre></div><div id="85cb"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_image_recognition</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.image_recognition</pre></div><div id="8f67"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_nlp</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.nlp</pre></div><div id="5f3f"><pre># Usage example: ai = <span class="hljs-built_in">ArtificialIntelligence</span>() ai.<span class="hljs-built_in">add_recommendation</span>(<span class="hljs-string">"Recommendation 1"</span>) ai.<span class="hljs-built_in">add_image_recognition</span>(<span class="hljs-string">"Image Recognition 1"</span>) ai.<span class="hljs-built_in">add_nlp</span>(<span class="hljs-string">"Natural Language Processing 1"</span>) <span class="hljs-built_in">print</span>(ai.<span class="hljs-built_in">get_recommendations</span>()) <span class="hljs-built_in">print</span>(ai.<span class="hljs-built_in">get_image_recognition</span>()) <span class="hljs-built_in">print</span>(ai.<span class="hljs-built_in">get_nlp</span>())</pre></div><p id="7396">Cross-border Trade:</p><div id="0dd3"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">CrossBorderTrade</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.buyers = [] <span class="hljs-variable language_">self</span>.suppliers = []</pre></div><div id="8ed2"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_buyer</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, buyer</span>): <span class="hljs-variable language_">self</span>.buyers.append(buyer)</pre></div><div id="d14c"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_supplier</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, supplier</span>): <span class="hljs-variable language_">self</span>.suppliers.append(supplier)</pre></div><div id="c4fa"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_buyers</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.buyers</pre></div><div id="b341"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_suppliers</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>.suppliers</pre></div><div id="0a59"><pre># Usage example: cross_border_trade = <span class="hljs-built_in">CrossBorderTrade</span>() cross_border_trade.<span class="hljs-built_in">add_buyer</span>(<span class="hljs-string">"Buyer 1"</span>) cross_border_trade.<span class="hljs-built_in">add_buyer</span>(<span class="hljs-string">"Buyer 2"</span>) cross_border_trade.<span class="hljs-built_in">add_supplier</span>(<span class="hljs-string">"Supplier 1"</span>) <span class="hljs-built_in">print</span>(cross_border_trade.<span class="hljs-built_in">get_buyers</span>()) <span class="hljs-built_in">print</span>(cross_border_trade.<span class="hljs-built_in">get_suppliers</span>())</pre></div><h1 id="2554">System Design — Substack</h1><p id="d44d">We will be discussing in depth -</p><ul><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>What is Substack</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Important Features</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Scaling Requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Data Model — ER requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>High Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Basic Low Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>API Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Complete Detailed Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Code implementation</b></a></li></ul><figure id="506d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*fqzEyv5SFwDn0UvF.jpg"><figcaption>Pic credits : Pinterest</figcaption></figure><h1 id="4cca">What is Substack</h1><p id="900e">Substack is a subscription-based publishing platform that enables writers to create and distribute newsletters to their audience. It provides a user-friendly interface for authors to compose and publish their content, while allowing readers to subscribe to their favorite newsletters and receive regular updates via email. Substack also offers monetization options, allowing authors to charge for premium content or offer paid subscriptions.</p><h1 id="e928">Important Features</h1><ul><li>User Registration and Authentication: Substack provides a seamless user registration process and ensures secure authentication for both authors and readers.</li><li>Newsletter Creation and Publishing: Authors can compose, format, and publish newsletters using a rich text editor with features like embedding media, adding images, and organizing content.</li><li>Subscription Management: Readers can easily discover and subscribe to newsletters of their interest, manage their subscription preferences, and receive email notifications for new issues.</li><li>Monetization Options: Substack facilitates monetization by enabling authors to offer paid subscriptions, create premium content, or receive voluntary contributions from readers.</li><li>Audience Interaction: Substack allows readers to engage with authors through comments, feedback, and replies, fostering a sense of community.</li><li>Analytics and Insights: Authors can access analytics to track newsletter performance, including subscriber growth, open rates, and engagement metrics.</li></ul><h1 id="d94c">Scaling Requirements — Capacity Estimation</h1><p id="2e15">Let’s assume —</p><ol><li>Total number of users: 10 million</li><li>Daily active users (DAU): 2 million</li><li>Average number of newsletters read by a user per day: 2</li><li>Total number of newsletters read per day: 4 million newsletters/day</li><li>Read-to-write ratio: 100:1 (as in the Netflix example)</li><li>Total number of newsletters created per day: 1/100 * 4 million = 40,000 newsletters/day</li></ol><p id="c0f9">Storage Estimation: Let’s assume an average newsletter size of 1 MB.</p><p id="a83b"><b><i>Total storage per day: 40,000 newsletters * 1 MB = 40 GB/day</i></b></p><p id="59c3"><b><i>For the next 3 years: 40 GB * 365 days * 3 years = 43.8 TB</i></b></p><p id="e103"><b><i>Requests per second: 4 million newsletters / (3600 seconds * 24 hours) = 46 newsletters/second</i></b></p><blockquote id="9b5c"><p>Horizontal Scalability: The platform should be designed to handle a high volume of concurrent user interactions, such as reading newsletters, subscribing, and commenting.</p></blockquote><blockquote id="057d"><p>Content Distribution: Efficient content delivery mechanisms, like content caching and content delivery networks (CDNs), should be employed to serve newsletters to readers across different geographical regions.</p></blockquote><blockquote id="1a12"><p>Robust Data Storage: The system should employ scalable and fault-tolerant databases to handle large amounts of user-generated content, including newsletters, user profiles, and subscription data.</p></blockquote><h1 id="c9d1">Data Model — ER requirements</h1><p id="ab5f">Users:</p><ul><li>Username: String</li><li>Email: String</li><li>Password: String</li></ul><p id="33d6">Posts:</p><ul><li>PostId: Int</li><li>User_id: Int (Foreign key referencing Users table)</li><li>Content: String</li><li>Timestamp: DateTime</li></ul><p id="1a57">Likes:</p><ul><li>Like_id: Int</li><li>User_id: Int (Foreign key referencing Users table)</li><li>Post_id: Int (Foreign key referencing Posts table)</li><li>Timestamp: DateTime</li></ul><p id="7045">Comments:</p><ul><li>Comment_id: Int</li><li>Post_id: Int (Foreign key referencing Posts table)</li><li>User_id: Int (Foreign key referencing Users table)</li><li>Caption_text: String</li><li>Timestamp: DateTime</li></ul><h1 id="31ce">High Level Design</h1><p id="ba81">Assumptions:</p><ol><li>There will be more reads than writes, so the system should be optimized for read operations.</li><li>Horizontal scaling will be used to handle increasing user demand.</li><li>High availability and reliability are crucial for the system.</li><li>Latency for feed generation should be around 350ms.</li><li>Consistency and reliability are more important than strict consistency.</li></ol><h1 id="a473">Main Components and Services:</h1><p id="da99">Mobile Client:</p><ul><li>Represents users accessing Substack via mobile devices.</li></ul><p id="b5fa">Application Servers:</p><ul><li>Responsible for handling read and write operations, as well as notification services.</li></ul><p id="e68b">Load Balancer:</p><ul><li>Routes and directs requests to the appropriate servers based on the designated services.</li></ul><p id="8179">Cache (e.g., Memcache):</p><ul><li>Utilized to improve performance by caching frequently accessed data based on the Least Recently Used (LRU) strategy.</li></ul><p id="07e4">CDN (Content Delivery Network):</p><ul><li>Enhances latency and throughput by caching and delivering static content closer to the users.</li></ul><p id="23b1">Database:</p><ul><li>Stores data based on the defined data model, allowing for efficient retrieval and storage.</li><li>NoSQL databases, like MongoDB or Cassandra, may be suitable for storing key-value pairs and capturing entity relationships.</li></ul><p id="65ea">Storage (e.g., Amazon S3):</p><ul><li>Used to upload and store photos, providing a reliable and scalable solution.</li></ul><h1 id="2615">Services:</h1><p id="3601">Like Service:</p><ul><li>Enables users to like a specific post.</li><li>Utilizes the data model to associate users with posts and timestamps.</li></ul><p id="2061">Follow Service:</p><ul><li>Allows users to follow other users.</li><li>Captures the relationship between User_id1 and User_id2.</li></ul><p id="cdc0">Comment Service:</p><ul><li>Provides functionality for users to comment on posts and reply to prior comments.</li><li>Stores the comment text, timestamps, and associations with the respective post and user.</li></ul><p id="dbf6">Post Service:</p><ul><li>Handles the creation and storage of posts.</li><li>Stores the post content, timestamps, and associations with the respective user.</li></ul><p id="a2e2">Generate Feed Service:</p><ul><li>Fetches recent, popular, and relevant posts from the users that the current user follows.</li><li>Utilizes ranking algorithms to score posts based on factors like likes, comments, and user activity.</li><li>Generates and stores user-specific feeds for efficient retrieval during login.</li></ul><div id="7e30"><pre><span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-comment"># User service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.users = []

<span class="hljs-keyword">def</span> <span class="hljs-title function_">register_user</span>(<span class="hljs-params">self, username, email, password</span>):
    user = {
        <span class="hljs-string">'username'</span>: username,
        <span class="hljs-string">'email'</span>: email,
        <span class="hljs-string">'password'</span>: password
    }
    self.users.append(user)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_by_username</span>(<span class="hljs-params">self, username</span>):
    <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> self.users:
        <span class="hljs-keyword">if</span> user[<span class="hljs-string">'username'</span>] == username:
            <span class="hljs-keyword">return</span> user
    <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

<span class="hljs-comment"># Post service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">PostService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.posts = [] self.post_id = <span class="hljs-number">1</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">create_post</span>(<span class="hljs-params">self, user_id, content</span>):
    post = {
        <span class="hljs-string">'post_id'</span>: self.post_id,
        <span class="hljs-string">'user_id'</span>: user_id,
        <span class="hljs-string">'content'</span>: content,
        <span class="hljs-string">'timestamp'</span>: datetime.now()
    }
    self.posts.append(post)
    self.post_id += <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> post

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_post_by_id</span>(<span class="hljs-params">self, post_id</span>):
    <span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> self.posts:
        <span class="hljs-keyword">if</span> post[<span class="hljs-string">'post_id'</span>] == post_id:
            <span class="hljs-keyword">return</span> post
    <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

<span class="hljs-comment"># Like service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">LikeService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.likes = [] self.like_id = <span class="hljs-number">1</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_like</span>(<span class="hljs-params">self, user_id, post_id</span>):
    like = {
        <span class="hljs-string">'like_id'</span>: self.like_id,
        <span class="hljs-string">'user_id'</span>: user_id,
        <span class="hljs-string">'post_id'</span>: post_id,
        <span class="hljs-string">'timestamp'</span>: datetime.now()
    }
    self.likes.append(like)
    self.like_id += <span class="hljs-number">1</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_likes_for_post</span>(<span class="hljs-params">self, post_id</span>):
    <span class="hljs-keyword">return</span> [like <span class="hljs-keyword">for</span> like <span class="hljs-keyword">in</span> self.likes <span class="hljs-keyword">if</span> like[<span class="hljs-string">'post_id'</span>] == post_id]

<span class="hljs-comment"># Comment service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">CommentService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.comments = [] self.comment_id = <span class="hljs-number">1</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_comment</span>(<span class="hljs-params">self, user_id, post_id, caption_text</span>):
    comment = {
        <span class="hljs-string">'comment_id'</span>: self.comment_id,
        <span class="hljs-string">'user_id'</span>: user_id,
        <span class="hljs-string">'post_id'</span>: post_id,
        <span class="hljs-string">'caption_text'</span>: caption_text,
        <span class="hljs-string">'timestamp'</span>: datetime.now()
    }
    self.comments.append(comment)
    self.comment_id += <span class="hljs-number">1</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_comments_for_post</span>(<span class="hljs-params">self, post_id</span>):
    <span class="hljs-keyword">return</span> [comment <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> self.comments <span class="hljs-keyword">if</span> comment[<span class="hljs-string">'post_id'</span>] == post_id]

<span class="hljs-comment"># Follow service</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">FollowService</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.follows = []

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_follow</span>(<span class="hljs-params">self, user_id1, user_id2</span>):
    follow = {
        <span class="hljs-string">'user_id1'</span>: user_id1,
        <span class="hljs-string">'user_id2'</span>: user_id2
    }
    self.follows.append(follow)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_followers_for_user</span>(<span class="hljs-params">self, user_id</span>):
    <span class="hljs-keyword">return</span> [follow[<span class="hljs-string">'user_id1'</span>] <span class="hljs-keyword">for</span> follow <span class="hljs-keyword">in</span> self.follows <span class="hljs-keyword">if</span> follow[<span class="hljs-string">'user_id2'</span>] == user_id]

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_following_for_user</span>(<span class="hljs-params">self, user_id</span>):
    <span class="hljs-keyword">return</span> [follow[<span class="hljs-string">'user_id2'</span>] <span class="hljs-keyword">for</span> follow <span class="hljs-keyword">in</span> self.follows <span class="hljs-keyword">if</span> follow[<span class="hljs-string">'user_id1'</span>] == user_id]

<span class="hljs-comment"># Usage example</span> user_service = UserService() post_service = PostService() like_service = LikeService() comment_service = CommentService() follow_service = FollowService()

<span class="hljs-comment"># Register users</span> user_service.register_user(<span class="hljs-string">'user1'</span>, <span class="hljs-string">'[email protected]'</span>, <span class="hljs-string">'password1'</span>) user_service.register_user(<span class="hljs-string">'user2'</span>, <span class="hljs-string">'[email protected]'</span>, <span class="hljs-string">'password2'</span>)

<span class="hljs-comment"># Create posts</span> post1 = post_service.create_post(<span class="hljs-number">1</span>, <span class="hljs-string">'This is my first post!'</span>) post2 = post_service.create_post(<span class="hljs-number">2</span>, <span class="hljs-string">'Hello world!'</span>)

<span class="hljs-comment"># Add likes</span> like_service.add_like(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>) like_service.add_like(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>)

<span class="hljs-comment"># Add comments</span> comment_service.add_comment(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-string">'Great post!'</span>) comment_service.add_comment(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-string">'Nice!'</span>)

<span class="hljs-comment"># Add follows</span> follow_service.add_follow(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)

<span class="hljs-comment"># Retrieve user-specific data</span> user1 = user_service.get_user_by_username(<span class="hljs-string">'user1'</span>) user2 = user_service.get_user_by_username(<span class="hljs-string">'user2'</span>) post1_likes = like_service.get_likes_for_post(<span class="hljs-number">1</span>) post1_comments = comment_service.get_comments_for_post(<span class="hljs-number">1</span>) user1_followers = follow_service.get_followers_for_user(<span class="hljs-number">1</span>) user1_following = follow_service.get_following_for_user(<span class="hljs-number">1</span>)

<span class="hljs-built_in">print</span>(<span class="hljs-string">"User 1:"</span>, user1) <span class="hljs-built_in">print</span>(<span class="hljs-string">"User 2:"</span>, user2) <span class="hljs-built_in">print</span>(<span class="hljs-string">"Likes for Post 1:"</span>, post1_likes) <span class="hljs-built_in">print</span>(<span class="hljs-string">"Comments for Post 1:"</span>, post1_comments) <span class="hljs-built_in">print</span>(<span class="hljs-string">"User 1's followers:"</span>, user1_followers) <span class="hljs-built_in">print</span>(<span class="hljs-string">"User 1's following:"</span>, user1_following)</pre></div><blockquote id="a26e"><p>Frontend Application: Responsible for the user interface, providing authoring tools, subscription management, and reader interactions.</p></blockquote><blockquote id="6433"><p>Backend Services: Handle core functionalities like user authentication, newsletter creation, content storage, subscription management, and payment processing.</p></blockquote><blockquote id="bafe"><p>Databases: Store user profiles, newsletter metadata, subscriptions, comments, and payment information.</p></blockquote><blockquote id="24b3"><p>Caching and CDN: Improve content delivery performance by caching frequently accessed newsletters and utilizing CDN services for global distribution.</p></blockquote><h1 id="5815">Basic Low Level Design</h1><div id="f129"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request

app = Flask(name)

<span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, user_id, username, password</span>): self.user_id = user_id self.username = username self.password = password <span class="hljs-comment"># other user attributes</span>

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Newsletter</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self, newsletter_id, author, title</span>): self.newsletter_id = newsletter_id self.author = author self.title = title <span class="hljs-comment"># other newsletter attributes</span>

<span class="hljs-keyword">class</span> <span class="hljs-title class_">Substack</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.users = [] self.newsletters = []

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_user</span>(<span class="hljs-params">self, user</span>):
    self.users.append(user)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_newsletter</span>(<span class="hljs-params">self, newsletter</span>):
    self.newsletters.append(newsletter)

substack = Substack()

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">register_user</span>(): data = request.get_json() user_id = <span class="hljs-built_in">len</span>(substack.users) + <span class="hljs-number">1</span> user = User(user_id, data[<span class="hljs-string">'username'</span>], data[<span class="hljs-string">'password'</span>]) substack.add_user(user) <span class="hljs-keyword">return</span> { <span class="hljs-string">'user_id'</span>: user.user_id, <span class="hljs-string">'message'</span>: <span class="hljs-string">'User registered successfully'</span> }

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/newsletters'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_newsletter</span>(): data = request.get_json() newsletter_id = <span class="hljs-built_in">len</span>(substack.newsletters) + <span class="hljs-number">1</span> newsletter = Newsletter(newsletter_id, data[<span class="hljs-string">'author'</span>], data[<span class="hljs-string">'title'</span>]) substack.add_newsletter(newsletter) <span class="hljs-keyword">return</span> { <span class="hljs-string">'newsletter_id'</span>: newsletter.newsletter_id, <span class="hljs-string">'message'</span>: <span class="hljs-string">'Newsletter created successfully'</span> }

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user</span>(<span class="hljs-params">user_id</span>): <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> substack.users: <span class="hljs-keyword">if</span> user.user_id == user_id: <span class="hljs-keyword">return</span> { <span class="hljs-string">'user_id'</span>: user.user_id, <span class="hljs-string">'username'</span>: user.username, <span class="hljs-string">'password'</span>: user.password } <span class="hljs-keyword">return</span> <span class="hljs-string">'User not found'</span>, <span class="hljs-number">404</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/newsletters/<int:newsletter_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_newsletter</span>(<span class="hljs-params">newsletter_id</span>): <span class="hljs-keyword">for</span> newsletter <span class="hljs-keyword">in</span> substack.newsletters: <span class="hljs-keyword">if</span> newsletter.newsletter_id == newsletter_id: <span class="hljs-keyword">return</span> { <span class="hljs-string">'newsletter_id'</span>: newsletter.newsletter_id, <span class="hljs-string">'author'</span>: newsletter.author, <span class="hljs-string">'title'</span>: newsletter.title } <span class="hljs-keyword">return</span> <span class="hljs-string">'Newsletter not found'</span>, <span class="hljs-number">404</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/subscribe/<int:newsletter_id>'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">subscribe_to_newsletter</span>(<span class="hljs-params">user_id, newsletter_id</span>): user = <span class="hljs-literal">None</span> newsletter = <span class="hljs-literal">None</span>

<span class="hljs-keyword">for</span> u <span class="hljs-keyword">in</span> substack.users:
    <span class="hljs-keyword">if</span> u.user_id == user_id:
        user = u
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> substack.newsletters:
    <span class="hljs-keyword">if</span> n.newsletter_id == newsletter_id:
        newsletter = n
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">if</span> user <span class="hljs-keyword">and</span> newsletter:
    <span class="hljs-comment"># Perform subscription logic</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">'User subscribed to the newsletter'</span>
<span class="hljs-keyword">else</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-string">'User or newsletter not found'</span>, <span class="hljs-number">404</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>/unsubscribe/<int:newsletter_id>'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">unsubscribe_from_newsletter</span>(<span class="hljs-params">user_id, newsletter_id</span>): user = <span class="hljs-literal">None</span> newsletter = <span class="hljs-literal">None</span>

<span class="hljs-keyword">for</span> u <span class="hljs-keyword">in</span> substack.users:
    <span class="hljs-keyword">if</span> u.user_id == user_id:
        user = u
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> substack.newsletters:
    <span class="hljs-keyword">if</span> n.newsletter_id == newsletter_id:
        newsletter = n
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">if</span> user <span class="hljs-keyword">and</span> newsletter:
    <span class="hljs-comment"># Perform unsubscription logic</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">'User unsubscribed from the newsletter'</span>
<span class="hljs-keyword">else</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-string">'User or newsletter not found'</span>, <span class="hljs-number">404</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()</pre></div><h1 id="6c02">API Design</h1><p id="f856">User Management API: This API handles user-related operations, including registration, login, and profile management.</p><div id="619a"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, request</pre></div><div id="69a6"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name)</pre></div><div id="feb7"><pre>@app.route(<span class="hljs-string">'/api/register'</span>, methods=[<span class="hljs-string">'POST'</span>]) def register_user(): # Handle <span class="hljs-keyword">user</span> registration logic username = request.json[<span class="hljs-string">'username'</span>] email = request.json[<span class="hljs-string">'email'</span>] <span class="hljs-keyword">password</span> = request.json[<span class="hljs-string">'password'</span>] # <span class="hljs-keyword">Perform</span> registration process # <span class="hljs-keyword">Return</span> success response <span class="hljs-keyword">or</span> appropriate error message</pre></div><div id="8286"><pre>@app.route(<span class="hljs-string">'/api/login'</span>, methods=[<span class="hljs-string">'POST'</span>]) def login_user(): # Handle <span class="hljs-keyword">user</span> <span class="hljs-keyword">login</span> logic username = request.json[<span class="hljs-string">'username'</span>] <span class="hljs-keyword">password</span> = request.json[<span class="hljs-string">'password'</span>] # <span class="hljs-keyword">Perform</span> <span class="hljs-keyword">login</span> process # <span class="hljs-keyword">Return</span> success response <span class="hljs-keyword">or</span> appropriate error message</pre></div><div id="2cfa"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/api/user/profile'</span>, methods=[<span class="hljs-string">'GET'</span>]) <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_profile</span>(): <span class="hljs-comment"># Handle fetching user profile logic</span> user_id = request.args.get(<span class="hljs-string">'user_id'</span>) <span class="hljs-comment"># Retrieve user profile information from the database</span> <span class="hljs-comment"># Return user profile data or appropriate error message</span></pre></div><div id="7ba0"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.<span class="hljs-built_in">run</span>()</pre></div><p id="ae3a">Newsletter API: This API enables authors to create, edit, and retrieve newsletters.</p><div id="af8f"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, request</pre></div><div id="3234"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name)</pre></div><div id="6730"><pre>@app.route(<span class="hljs-string">'/api/newsletter'</span>, methods=[<span class="hljs-string">'POST'</span>]) def create_newsletter(): # Handle creating a <span class="hljs-built_in">new</span> newsletter author_id = request.json[<span class="hljs-string">'author_id'</span>] title = request.json[<span class="hljs-string">'title'</span>] content = request.json[<span class="hljs-string">'content'</span>] # <span class="hljs-keyword">Perform</span> newsletter creation process # <span class="hljs-keyword">Return</span> success response <span class="hljs-keyword">or</span> appropriate error message</pre></div><div id="dc46"><pre>@app.route(<span class="hljs-string">'/api/newsletter/<newsletter_id>'</span>, methods=[<span class="hljs-string">'PUT'</span>]) def edit_newsletter(newsletter_id): # Handle editing an existing newsletter title = request.json[<span class="hljs-string">'title'</span>] content = request.json[<span class="hljs-string">'content'</span>] # <span class="hljs-keyword">Perform</span> newsletter editing process # <span class="hljs-keyword">Return</span> success response <span class="hljs-keyword">or</span> appropriate error message</pre></div><div id="0808"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/newsletter/<newsletter_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_newsletter</span>(<span class="hljs-params">newsletter_id</span>): <span class="hljs-comment"># Handle fetching a specific newsletter</span> <span class="hljs-comment"># Retrieve newsletter data from the database</span> <span class="hljs-comment"># Return newsletter data or appropriate error message</span></pre></div><div id="ecde"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.<span class="hljs-built_in">run</span>()</pre></div><div id="f3bc"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, request <span class="hljs-keyword">from</span> low_level_api <span class="hljs-keyword">import</span> register_user, login_user, get_user_profile, create_newsletter, edit_newsletter, get_newsletter</pre></div><div id="48f1"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name)</pre></div><div id="9a4b"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/api/user/register'</span>, methods=[<span class="hljs-string">'POST'</span>]) <span class="hljs-keyword">def</span> <span class="hljs-title function_">high_level_register_user</span>(): <span class="hljs-keyword">return</span> register_user(request.json)</pre></div><div id="e62b"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/api/user/login'</span>, methods=[<span class="hljs-string">'POST'</span>]) <span class="hljs-keyword">def</span> <span class="hljs-title function_">high_level_login_user</span>(): <span class="hljs-keyword">return</span> login_user(request.json)</pre></div><div id="9123"><pre><span class="hljs-variable">@app</span>.<span class="hljs-built_in">route</span>(<span class="hljs-string">'/api/user/profile'</span>, methods=[<span class="hljs-string">'GET'</span>]) def <span class="hljs-built_in">high_level_get_user_profile</span>(): user_id = request.args.<span class="hljs-built_in">get</span>(<span class="hljs-string">'user_id'</span>) return <span class="hljs-built_in">get_user_profile</span>(user_id)</pre></div><div id="7d7b"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/api/newsletter'</span>, methods=[<span class="hljs-string">'POST'</span>]) <span class="hljs-keyword">def</span> <span class="hljs-title function_">high_level_create_newsletter</span>(): <span class="hljs-keyword">return</span> create_newsletter(request.json)</pre></div><div id="cd53"><pre><span class="hljs-meta">@app.route</span>(<span class="hljs-string">'/api/newsletter/<newsletter_id>'</span>, methods=[<span class="hljs-string">'PUT'</span>]) def high_level_edit_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_id</span>):<span class="hljs-type"></span> <span class="hljs-keyword">return</span> edit_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_id</span>, request.json)</pre></div><div id="4a04"><pre><span class="hljs-meta">@app.route</span>(<span class="hljs-string">'/api/newsletter/<newsletter_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]) def high_level_get_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_id</span>):<span class="hljs-type"></span> <span class="hljs-keyword">return</span> get_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_id</span>)</pre></div><div id="fbce"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.<span class="hljs-built_in">run</span>()</pre></div><h1 id="02f8">Complete Detailed Design</h1><p id="9bdf"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="00e1"><i>Subscribe to youtube channel :</i></p><div id="ff94" class="link-block"> <a href="https://www.youtube.com/@ignito5917/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div> </div> </div> </a> </div><h1 id="4dfb">Complete Code implementation</h1><p id="c1a0">User Registration and Authentication:</p><div id="d75d"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, username, email, password</span>): <span class="hljs-variable language_">self</span>.username = username <span class="hljs-variable language_">self</span>.email = email <span class="hljs-variable language_">self</span>.password = password</pre></div><div id="195a"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Substack</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.users = []</pre></div><div id="7db7"><pre> def register_user(self, username, email, <span class="hljs-keyword">password</span>): <span class="hljs-keyword">user</span> = <span class="hljs-keyword">User</span>(username, email, <span class="hljs-keyword">password</span>) self.users.append(<span class="hljs-keyword">user</span>)</pre></div><div id="9cde"><pre> def authenticate_user(self, username, password): for <span class="hljs-literal">user</span> in self.users: if <span class="hljs-literal">user</span>.username == username and <span class="hljs-literal">user</span>.password == password: <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span> <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span></pre></div><div id="78a4"><pre>substack = <span class="hljs-built_in">Substack</span>() substack<span class="hljs-selector-class">.register_user</span>(<span class="hljs-string">"john_doe"</span>, <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password123"</span>) authenticated = substack<span class="hljs-selector-class">.authenticate_user</span>(<span class="hljs-string">"john_doe"</span>, <span class="hljs-string">"password123"</span>) <span class="hljs-function"><span class="hljs-title">print</span><span class="hljs-params">(<span class="hljs-string">"Authentication successful:"</span>, authenticated)</span></span></pre></div><p id="7e92">Newsletter Creation and Publishing:</p><div id="9fce"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Newsletter</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, author, title, content</span>): <span class="hljs-variable language_">self</span>.author = author <span class="hljs-variable language_">self</span>.title = title <span class="hljs-variable language_">self</span>.content = content</pre></div><div id="9c38"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Substack</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.newsletters = []</pre></div><div id="8f57"><pre> def create_new<span class="hljs-type">sletter</span>(self, author, title, content):<span class="hljs-type"></span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = Newsletter(author, title, content) self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>.append(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="73bb"><pre> def publish_new<span class="hljs-type">sletter</span>(self, <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>):<span class="hljs-type"></span> print(<span class="hljs-string">"Publishing Newsletter"</span>) print(<span class="hljs-string">"Author:"</span>, <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.author) print(<span class="hljs-string">"Title:"</span>, <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.title) print(<span class="hljs-string">"Content:"</span>, <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.content)</pre></div><div id="4134"><pre>substack = Substack() substack.create_new<span class="hljs-type">sletter</span>(<span class="hljs-string">"John Doe"</span>, <span class="hljs-string">"Weekly Digest"</span>, <span class="hljs-string">"Lorem ipsum dolor sit amet..."</span>) <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = substack.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>[<span class="hljs-number">0</span>] substack.publish_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><p id="838d">Subscription Management:</p><div id="ffb2"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, username</span>): <span class="hljs-variable language_">self</span>.username = username <span class="hljs-variable language_">self</span>.subscriptions = []</pre></div><div id="f865"><pre> def subscribe_to_new<span class="hljs-type">sletter</span>(self, <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>):<span class="hljs-type"></span> self.subscriptions.append(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="9dbe"><pre> def unsubscribe_from_new<span class="hljs-type">sletter</span>(self, <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>):<span class="hljs-type"></span> self.subscriptions.remove(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="f6d6"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Substack</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.users = [] <span class="hljs-variable language_">self</span>.newsletters = []</pre></div><div id="95a9"><pre> def create_new<span class="hljs-type">sletter</span>(self, author, title, content):<span class="hljs-type"></span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = Newsletter(author, title, content) self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>.append(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="2b25"><pre> def subscribe_user_to_new<span class="hljs-type">sletter</span>(self, username, <span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>):<span class="hljs-type"></span> user = self.get_user(username) <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = self.get_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>) <span class="hljs-keyword">if</span> user and <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>: user.subscribe_to_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="b53d"><pre> def unsubscribe_user_from_new<span class="hljs-type">sletter</span>(self, username, <span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>):<span class="hljs-type"></span> user = self.get_user(username) <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = self.get_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>) <span class="hljs-keyword">if</span> user and <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>: user.unsubscribe_from_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="049d"><pre> def get_user(self, username): for <span class="hljs-keyword">user</span> <span class="hljs-title">in</span> self.users: if user.username == username: return <span class="hljs-keyword">user</span> <span class="hljs-title">return</span> None</pre></div><div id="c818"><pre> def get_new<span class="hljs-type">sletter</span>(self, title):<span class="hljs-type"></span> <span class="hljs-keyword">for</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> <span class="hljs-keyword">in</span> self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>: <span class="hljs-keyword">if</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.title == title:<span class="hljs-type"></span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> <span class="hljs-keyword">return</span> None</pre></div><p id="cc7f">Monetization Options: (Example with paid subscriptions)</p><div id="6ec9"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, username</span>): <span class="hljs-variable language_">self</span>.username = username <span class="hljs-variable language_">self</span>.subscriptions = [] <span class="hljs-variable language_">self</span>.paid_subscriptions = []</pre></div><div id="8420"><pre> def subscribe_to_new<span class="hljs-type">sletter</span>(self, <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>):<span class="hljs-type"></span> self.subscriptions.append(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="f666"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">purchase_paid_subscription</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, newsletter</span>): <span class="hljs-variable language_">self</span>.paid_subscriptions.append(newsletter)</pre></div><div id="b885"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Substack</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.users = [] <span class="hljs-variable language_">self</span>.newsletters = []</pre></div><div id="45b2"><pre> def create_new<span class="hljs-type">sletter</span>(self, author, title, content):<span class="hljs-type"></span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = Newsletter(author, title, content) self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>.append(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="8e98"><pre> def subscribe_user_to_new<span class="hljs-type">sletter</span>(self, username, <span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>):<span class="hljs-type"></span> user = self.get_user(username) <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = self.get_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>) <span class="hljs-keyword">if</span> user and <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>: user.subscribe_to_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="21d2"><pre> def purchase_subscription(self, username, <span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>):<span class="hljs-type"></span> user = self.get_user(username) <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = self.get_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>) <span class="hljs-keyword">if</span> user and <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>: user.purchase_paid_subscription(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="0dec"><pre> def get_user(self, username): for <span class="hljs-keyword">user</span> <span class="hljs-title">in</span> self.users: if user.username == username: return <span class="hljs-keyword">user</span> <span class="hljs-title">return</span> None</pre></div><div id="743e"><pre> def get_new<span class="hljs-type">sletter</span>(self, title):<span class="hljs-type"></span> <span class="hljs-keyword">for</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> <span class="hljs-keyword">in</span> self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>: <span class="hljs-keyword">if</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.title == title:<span class="hljs-type"></span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> <span class="hljs-keyword">return</span> None</pre></div><p id="27c7">Audience Interaction:</p><div id="6449"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Comment</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, user, content</span>): <span class="hljs-variable language_">self</span>.user = user <span class="hljs-variable language_">self</span>.content = content</pre></div><div id="fd57"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Newsletter</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, author, title, content</span>): <span class="hljs-variable language_">self</span>.author = author <span class="hljs-variable language_">self</span>.title = title <span class="hljs-variable language_">self</span>.content = content <span class="hljs-variable language_">self</span>.comments = []</pre></div><div id="316a"><pre> def add_comment(self, <span class="hljs-keyword">user</span>, content): <span class="hljs-keyword">comment</span> = <span class="hljs-keyword">Comment</span>(<span class="hljs-keyword">user</span>, content) self.comments.append(<span class="hljs-keyword">comment</span>)</pre></div><div id="1836"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Substack</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.newsletters = []</pre></div><div id="4a5f"><pre> def create_new<span class="hljs-type">sletter</span>(self, author, title, content):<span class="hljs-type"></span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = Newsletter(author, title, content) self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>.append(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="eae1"><pre> def add_comment_to_new<span class="hljs-type">sletter</span>(self, <span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>, user, content):<span class="hljs-type"></span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = self.get_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>) <span class="hljs-keyword">if</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>: <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.add_comment(user, content)</pre></div><div id="14a5"><pre> def get_new<span class="hljs-type">sletter</span>(self, title):<span class="hljs-type"></span> <span class="hljs-keyword">for</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> <span class="hljs-keyword">in</span> self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>: <span class="hljs-keyword">if</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.title == title:<span class="hljs-type"></span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> <span class="hljs-keyword">return</span> None</pre></div><div id="b0fb"><pre><span class="hljs-attribute">substack</span> <span class="hljs-operator">=</span> Substack() </pre></div><p id="04ad">Analytics and Insights:</p><div id="bf82"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Newsletter</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, author, title, content</span>): <span class="hljs-variable language_">self</span>.author = author <span class="hljs-variable language_">self</span>.title = title <span class="hljs-variable language_">self</span>.content = content <span class="hljs-variable language_">self</span>.subscribers = []</pre></div><div id="1ee9"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_subscriber</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, user</span>): <span class="hljs-variable language_">self</span>.subscribers.append(user)</pre></div><div id="fd09"><pre> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_subscriber_count</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-keyword">return</span> len(<span class="hljs-variable language_">self</span>.subscribers)</pre></div><div id="45d3"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Substack</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>): <span class="hljs-variable language_">self</span>.newsletters = []</pre></div><div id="b99c"><pre> def create_new<span class="hljs-type">sletter</span>(self, author, title, content):<span class="hljs-type"></span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = Newsletter(author, title, content) self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>.append(<span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>)</pre></div><div id="55d7"><pre> def subscribe_user_to_new<span class="hljs-type">sletter</span>(self, <span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>, user):<span class="hljs-type"></span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> = self.get_new<span class="hljs-type">sletter</span>(<span class="hljs-keyword">new</span><span class="hljs-type">sletter_title</span>) <span class="hljs-keyword">if</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>: <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.add_subscriber(user)</pre></div><div id="0dfb"><pre> def get_new<span class="hljs-type">sletter</span>(self, title):<span class="hljs-type"></span> <span class="hljs-keyword">for</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> <span class="hljs-keyword">in</span> self.<span class="hljs-keyword">new</span><span class="hljs-type">sletters</span>: <span class="hljs-keyword">if</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span>.title == title:<span class="hljs-type"></span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span><span class="hljs-type">sletter</span> <span class="hljs-keyword">return</span> None</pre></div><div id="8c30"><pre><span class="hljs-attribute">substack</span> <span class="hljs-operator">=</span> Substack() </pre></div><h1 id="29e7">System Design — Instant Messenger</h1><p id="e639">We will be discussing in depth -</p><ul><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>What is Instant Messenger</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Important Features</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Scaling Requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Data Model — ER requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>High Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Basic Low Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>API Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Complete Detailed Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Code implementation</b></a></li></ul><figure id="1ade"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*dl4RRuXnjeoZvzTC"><figcaption>Pic credits : Pinterest</figcaption></figure><h1 id="0ab8">What is Instant Messenger</h1><p id="0e09">Instant Messenger (IM) is a real-time communication application that enables users to exchange text messages, multimedia files, and other content over the internet. It facilitates instant, one-to-one or group messaging between individuals and allows for seamless and quick interactions.</p><h1 id="8540">Important Features</h1><ol><li>Real-Time Messaging: Users can exchange messages in real-time, enabling instant communication.</li><li>User Authentication: Secure login and authentication mechanisms to ensure privacy and data protection.</li><li>Contacts and Friends List: Ability to add, manage, and organize contacts or friends for easy messaging.</li><li>Presence Status: Displaying the online/offline status of contacts to know their availability.</li><li>Message Delivery and Read Receipts: Indicating the status of sent messages, such as delivered and read.</li><li>Multimedia Sharing: Supporting the exchange of images, videos, and files alongside text messages.</li><li>Push Notifications: Sending notifications to users for new messages or updates even when the app is not active.</li><li>Emojis and Stickers: Allowing users to express emotions and add fun elements to their conversations.</li><li>Group Chats: Enabling users to create and participate in group conversations with multiple participants.</li><li>Message Search: Facilitating quick searching of past conversations for specific messages.</li><li>End-to-End Encryption: Ensuring that messages are encrypted and secure from unauthorized access.</li></ol><h1 id="ca4c">Scaling Requirements — Capacity Estimation</h1><p id="19d2">Let’s do a smaill scale simualtion for IM:</p><p id="dc6c">Scalability Requirements:</p><ul><li><i>Total number of users: 1.2 Billion</i></li><li><i>Daily active users (DAU): 300 million</i></li><li><i>Average number of messages sent by a user per day: 10</i></li><li><i>Total number of messages sent per day: 3 Billion messages/day</i></li><li><i>Read-to-write ratio: 100:1</i></li></ul><p id="e83d">Storage Estimation:</p><ul><li>Let’s assume on average each message size is 1KB</li><li>Total Storage per day: 3 Billion * 1KB = 3 TB/day</li><li>For the next 3 years: 3 TB * 5 * 365 = 5.475 PB</li></ul><p id="7f63">Requests per Second:</p><ul><li>Messages sent per second: 3 Billion / (24 hours * 3600 seconds) ≈ 34,722 messages/second</li></ul><div id="aaf1"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">InstantMessenger</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.users = {} self.messages = []

<span class="hljs-keyword">def</span> <span class="hljs-title function_">send_message</span>(<span class="hljs-params">self, sender_id, receiver_id, content</span>):
    <span class="hljs-comment"># Check if both sender and receiver exist</span>
    <span class="hljs-keyword">if</span> sender_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.users <span class="hljs-keyword">or</span> receiver_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.users:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid sender or receiver"</span>

    <span class="hljs-comment"># Create a new message and add it to the messages list</span>
    message = {
        <span class="hljs-string">"sender_id"</span>: sender_id,
        <span class="hljs-string">"receiver_id"</span>: receiver_id,
        <span class="hljs-string">"content"</span>: content
    }
    self.messages.append(message)
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Message sent successfully"</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_user</span>(<span class="hljs-params">self, user_id, username</span>):
    <span class="hljs-comment"># Add a new user to the system</span>
    self.users[user_id] = {<span class="hljs-string">"user_id"</span>: user_id, <span class="hljs-string">"username"</span>: username}

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_messages</span>(<span class="hljs-params">self, user_id</span>):
    <span class="hljs-comment"># Retrieve all messages for a given user</span>
    user_messages = [message <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> self.messages <span class="hljs-keyword">if</span> message[<span class="hljs-string">'sender_id'</span>] == user_id <span class="hljs-keyword">or</span> message[<span class="hljs-string">'receiver_id'</span>] == user_id]
    <span class="hljs-keyword">return</span> user_messages

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: <span class="hljs-comment"># Create an instance of the InstantMessenger</span> im = InstantMessenger()

<span class="hljs-comment"># Add users to the system</span>
<span class="hljs-keyword">for</span> user_id <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, <span class="hljs-number">300001</span>):  <span class="hljs-comment"># Assuming user IDs start from 1 and go up to 300,000</span>
    im.add_user(user_id, <span class="hljs-string">f"user_<span class="hljs-subst">{user_id}</span>"</span>)

<span class="hljs-comment"># Simulate message sending for a day</span>
<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">10</span>):  <span class="hljs-comment"># Assume 10 iterations for 10 days</span>
    <span class="hljs-keyword">for</span> user_id <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, <span class="hljs-number">300001</span>):
        <span class="hljs-comment"># Simulate sending 10 messages by each user</span>
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">10</span>):
            receiver_id = user_id + <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> user_id &lt; <span class="hljs-number">300000</span> <span class="hljs-keyword">else</span> <span class="hljs-number">1</span>  <span class="hljs-comment"># Loop around users for simplicity</span>
            message_content = <span class="hljs-string">f"Hello from user_<span class="hljs-subst">{user_id}</span>, message <span class="hljs-subst">{i+<span class="hljs-number">1</span>}</span>"</span>
            im.send_message(user_id, receiver_id, message_content)

<span class="hljs-comment"># Retrieve messages for a specific user (e.g., user with ID 1)</span>
user1_messages = im.get_user_messages(<span class="hljs-number">1</span>)
<span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> user1_messages:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">f"From: user_<span class="hljs-subst">{message[<span class="hljs-string">'sender_id'</span>]}</span> To: user_<span class="hljs-subst">{message[<span class="hljs-string">'receiver_id'</span>]}</span> Content: <span class="hljs-subst">{message[<span class="hljs-string">'content'</span>]}</span>"</span>)</pre></div><h1 id="9cb8">Data Model — ER requirements</h1><ol><li>User: Stores user details such as UserID, Username, Password, Email, etc.</li><li>Contact/Friend: Represents the relationship between users, indicating who are contacts or friends.</li><li>Message: Contains message details such as MessageID, Content, Timestamp, SenderID, ReceiverID, etc.</li><li>Group: Stores information about group chats, including GroupID, GroupName, Members, etc.</li></ol><h1 id="8eaf">High Level Design</h1><ol><li>Horizontal Scalability: The system should be able to distribute the load across multiple servers to handle increased user traffic.</li><li>Data Partitioning: Messages and user data should be partitioned to avoid hotspots and distribute the database load.</li><li>Caching: Implementing caching mechanisms to reduce database queries and improve response times.</li><li>Load Balancing: Using load balancers to distribute incoming requests evenly among multiple servers.</li><li>Asynchronous Processing: Decoupling time-consuming tasks (e.g., message delivery) to be processed asynchronously.</li><li>Client Application: Responsible for rendering the user interface, managing user interactions, and sending/receiving messages through APIs.</li><li>API Gateway: Acts as an entry point for client requests, authenticates users, and forwards requests to appropriate services.</li><li>User Service: Handles user-related operations such as user creation, authentication, and friend management.</li><li>Message Service: Manages message-related operations like sending, receiving, and deleting messages.</li><li>Group Service: Handles group chat operations, including group creation and member management.</li><li>Push Notification Service: Sends push notifications to users for new messages or updates.</li><li>WebSockets: Enables real-time bidirectional communication between the server and the client.</li><li>Caching Service: Stores frequently accessed data to reduce database queries and improve performance.</li><li>Mobile Client: Users will access the Instant Messenger platform through mobile applications.</li><li>Application Servers: Responsible for handling read, write, and notification services. These servers manage user authentication, message sending, receiving, and processing various user actions.</li><li>Load Balancer: Routes and directs incoming requests from mobile clients to the appropriate application servers based on load distribution.</li><li>Cache (Memcache): Caches frequently accessed data, such as user details and recent messages, to reduce database queries and improve response times.</li><li>Database: Stores user data, messages, contacts, and group information.</li></ol><h1 id="9513">Main Components and Services</h1><p id="dd9f">User Service:</p><ul><li>User Registration: Allows users to register with a unique username, email, and password.</li><li>User Login: Authenticates users with their credentials and provides access to the Instant Messenger platform.</li><li>User Profile: Retrieves user details such as username, email, and other profile information.</li></ul><p id="d504">Message Service:</p><ul><li>Send Message: Enables users to send messages to other users or groups.</li><li>Receive Message: Delivers messages to the intended recipients and notifies them of new messages.</li><li>Message History: Retrieves the message history for a user or group.</li></ul><p id="24d8">Contact Service:</p><ul><li>Add Contact: Allows users to add other users as contacts for easy messaging.</li><li>Remove Contact: Enables users to remove contacts from their contact list.</li></ul><p id="99b3">Group Service:</p><ul><li>Create Group: Allows users to create new groups for group conversations.</li><li>Add/Remove Group Members: Enables users to add or remove members from a group.</li></ul><p id="a9a0">Feed Generation Service:</p><ul><li>Generates and curates the user’s feed, showing recent and relevant messages from contacts and groups.</li></ul><p id="adbb">Notification Service:</p><ul><li>Sends push notifications to users for new messages, contact requests, and group invitations.</li></ul><p id="38e8">Search Service:</p><ul><li>Facilitates quick searching of past conversations and users.</li></ul><p id="2ff2">Encryption Service:</p><ul><li>Ensures end-to-end encryption for messages to ensure data security and privacy.</li></ul><div id="9c4f"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">InstantMessenger</span>:
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
    self.users = {}
    self.messages = []
    self.contacts = {}
    self.groups = {}
    self.feed = {}

<span class="hljs-comment"># User Service</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">register_user</span>(<span class="hljs-params">self, username, email, password</span>):
    user_id = <span class="hljs-built_in">len</span>(self.users) + <span class="hljs-number">1</span>
    user = {
        <span class="hljs-string">"user_id"</span>: user_id,
        <span class="hljs-string">"username"</span>: username,
        <span class="hljs-string">"email"</span>: email,
        <span class="hljs-string">"password"</span>: password
    }
    self.users[user_id] = user
    <span class="hljs-keyword">return</span> user

<span class="hljs-keyword">def</span> <span class="hljs-title function_">login_user</span>(<span class="hljs-params">self, username, password</span>):
    <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> self.users.values():
        <span class="hljs-keyword">if</span> user[<span class="hljs-string">'username'</span>] == username <span class="hljs-keyword">and</span> user[<span class="hljs-string">'password'</span>] == password:
            <span class="hljs-keyword">return</span> user
    <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_profile</span>(<span class="hljs-params">self, user_id</span>):
    <span class="hljs-keyword">return</span> self.users.get(user_id, <span class="hljs-literal">None</span>)

<span class="hljs-comment"># Message Service</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">send_message</span>(<span class="hljs-params">self, sender_id, receiver_id, content</span>):
    message_id = <span class="hljs-built_in">len</span>(self.messages) + <span class="hljs-number">1</span>
    message = {
        <span class="hljs-string">"message_id"</span>: message_id,
        <span class="hljs-string">"sender_id"</span>: sender_id,
        <span class="hljs-string">"receiver_id"</span>: receiver_id,
        <span class="hljs-string">"content"</span>: content
    }
    self.messages.append(message)
    self._notify_receiver(receiver_id, message)
    <span class="hljs-keyword">return</span> message

<span class="hljs-keyword">def</span> <span class="hljs-title function_">_notify_receiver</span>(<span class="hljs-params">self, receiver_id, message</span>):
    <span class="hljs-comment"># Simulating push notifications</span>
    <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Notification: You have a new message from <span class="hljs-subst">{message[<span class="hljs-string">'sender_id'</span>]}</span>"</span>)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_messages</span>(<span class="hljs-params">self, user_id</span>):
    user_messages = [message <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> self.messages <span class="hljs-keyword">if</span> message[<span class="hljs-string">'sender_id'</span>] == user_id <span class="hljs-keyword">or</span> message[<span class="hljs-string">'receiver_id'</span>] == user_id]
    <span class="hljs-keyword">return</span> user_messages

<span class="hljs-comment"># Contact Service</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_contact</span>(<span class="hljs-params">self, user_id, contact_id</span>):
    <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.contacts:
        self.contacts[user_id] = <span class="hljs-built_in">set</span>()
    self.contacts[user_id].add(contact_id)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">remove_contact</span>(<span class="hljs-params">self, user_id, contact_id</span>):
    <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">in</span> self.contacts:
        self.contacts[user_id].discard(contact_id)

<span class="hljs-comment"># Group Service</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">create_group</span>(<span class="hljs-params">self, group_name, user_ids</span>):
    group_id = <span class="hljs-built_in">len</span>(self.groups) + <span class="hljs-number">1</span>
    group = {
        <span class="hljs-string">"group_id"</span>: group_id,
        <span class="hljs-string">"group_name"</span>: group_name,
        <span class="hljs-string">"members"</span>: user_ids
    }
    self.groups[group_id] = group
    <span class="hljs-keyword">return</span> group

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_member_to_group</span>(<span class="hljs-params">self, group_id, user_id</span>):
    <span class="hljs-keyword">if</span> group_id <span class="hljs-keyword">in</span> self.groups:
        self.groups[group_id][<span class="hljs-string">"members"</span>].append(user_id)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">remove_member_from_group</span>(<span class="hljs-params">self, group_id, user_id</span>):
    <span class="hljs-keyword">if</span> group_id <span class="hljs-keyword">in</span> self.groups:
        self.groups[group_id][<span class="hljs-string">"members"</span>].remove(user_id)

<span class="hljs-comment"># Feed Generation Service</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">generate_feed</span>(<span class="hljs-params">self, user_id</span>):
    user_contacts = self.contacts.get(user_id, <span class="hljs-built_in">set</span>())
    user_groups = [group <span class="hljs-keyword">for</span> group <span class="hljs-keyword">in</span> self.groups.values() <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">in</span> group[<span class="hljs-string">"members"</span>]]
    feed = self.get_user_messages(user_id)
    <span class="hljs-keyword">for</span> contact_id <span class="hljs-keyword">in</span> user_contacts:
        feed.extend(self.get_user_messages(contact_id))
    <span class="hljs-keyword">for</span> group <span class="hljs-keyword">in</span> user_groups:
        <span class="hljs-keyword">for</span> member_id <span class="hljs-keyword">in</span> group[<span class="hljs-string">"members"</span>]:
            <span class="hljs-keyword">if</span> member_id != user_id:
                feed.extend(self.get_user_messages(member_id))
    self.feed[user_id] = <span class="hljs-built_in">sorted</span>(feed, key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-string">'message_id'</span>], reverse=<span class="hljs-literal">True</span>)[:<span class="hljs-number">50</span>]

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_feed</span>(<span class="hljs-params">self, user_id</span>):
    <span class="hljs-keyword">return</span> self.feed.get(user_id, [])

<span class="hljs-comment"># Notification Service</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">send_notification</span>(<span class="hljs-params">self, user_id, notification</span>):
    <span class="hljs-comment"># Simulating push notifications</span>
    <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Notification to User <span class="hljs-subst">{user_id}</span>: <span class="hljs-subst">{notification}</span>"</span>)

<span class="hljs-comment"># Search Service</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">search_messages</span>(<span class="hljs-params">self, query</span>):
    search_results = [message <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> self.messages <span class="hljs-keyword">if</span> query <span class="hljs-keyword">in</span> message[<span class="hljs-string">'content'</span>]]
    <span class="hljs-keyword">return</span> search_results

<span class="hljs-keyword">def</span> <span class="hljs-title function_">search_users</span>(<span class="hljs-params">self, query</span>):
    search_results = [user <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> self.users.values() <span class="hljs-keyword">if</span> query <span class="hljs-keyword">in</span> user[<span class="hljs-string">'username'</span>]]
    <span class="hljs-keyword">return</span> search_results

<span class="hljs-comment"># Encryption Service</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">encrypt_message</span>(<span class="hljs-params">self, message_content</span>):
    <span class="hljs-comment"># Implement encryption logic here (e.g., using cryptography libraries)</span>
    encrypted_content = <span class="hljs-string">"Encrypted: "</span> + message_content
    <span class="hljs-keyword">return</span> encrypted_content

<span class="hljs-keyword">def</span> <span class="hljs-title function_">decrypt_message</span>(<span class="hljs-params">self, encrypted_content</span>):
    <span class="hljs-comment"># Implement decryption logic here (e.g., using cryptography libraries)</span>
    decrypted_content = encrypted_content.replace(<span class="hljs-string">"Encrypted: "</span>, <span class="hljs-string">""</span>)
    <span class="hljs-keyword">return</span> decrypted_content

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: im = InstantMessenger()

<span class="hljs-comment"># User Service</span>
user1 = im.register_user(<span class="hljs-string">"user1"</span>, <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password1"</span>)
user2 = im.register_user(<span class="hljs-string">"user2"</span>, <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password2"</span>)

user1 = im.login_user(<span class="hljs-string">"user1"</span>, <span class="hljs-string">"password1"</span>)
user2 = im.login_user(<span class="hljs-string">"user2"</span>, <span class="hljs-string">"password2"</span>)

user1_profile = im.get_user_profile(user1[<span class="hljs-string">'user_id'</span>])
user2_profile = im.get_user_profile(user2[<span class="hljs-string">'user_id'</span>])

<span class="hljs-comment"># Message Service</span>
im.send_message(user1[<span class="hljs-string">'user_id'</span>], user2[<span class="hljs-string">'user_id'</span>], <span class="hljs-string">"Hello, User2!"</span>)
im.send_message(user2[<span class="hljs-string">'user_id'</span>], user1[<span class="hljs-string">'user_id'</span>], <span class="hljs-string">"Hi, User1!"</span>)

user1_messages = im.get_user_messages(user1[<span class="hljs-string">'user_id'</span>])
user2_messages = im.get_user_messages(user2[<span class="hljs-string">'user_id'</span>])

<span class="hljs-comment"># Contact Service</span>
im.add_contact(user1[<span class="hljs-string">'user_id'</span>], user2[<span class="hljs-string">'user_id'</span>])
im.remove_contact(user1[<span class="hljs-string">'user_id'</span>], user2[<span class="hljs-string">'user_id'</span>])

<span class="hljs-comment"># Group Service</span>
group1 = im.create_group(<span class="hljs-string">"Family Group"</span>, [user1[<span class="hljs-string">'user_id'</span>], user2[<span class="hljs-string">'user_id'</span>]])
im.add_member_to_group(group1[<span class="hljs-string">'group_id'</span>], user1[<span class="hljs-string">'user_id'</span>])
im.remove_member_from_group(group1[<span class="hljs-string">'group_id'</span>], user1[<span class="hljs-string">'user_id'</span>])

<span class="hljs-comment"># Feed Generation Service</span>
im.generate_feed(user1[<span class="hljs-string">'user_id'</span>])
user1_feed = im.get_user_feed(user1[<span class="hljs-string">'user_id'</span>])

<span class="hljs-comment"># Notification Service</span>
im.send_notification(user2[<span class="hljs-string">'user_id'</span>], <span class="hljs-string">"You have a new message from User1!"</span>)

<span class="hljs-comment"># Search Service</span>
search_results = im.search_messages(<span class="hljs-string">"Hello"</span>)

<span class="hljs-comment"># Encryption Service</span>
encrypted_message = im.encrypt_message(<span class="hljs-string">"Hello, User2!"</span>)
decrypted_message = im.decrypt_message(encrypted_message)</pre></div><h1 id="aca6">Basic Low Level Design</h1><div id="9ab8"><pre><span class="hljs-comment"># Sample data to represent user and message storage (Replace this with a database in a real implementation)</span>

users = { <span class="hljs-number">1</span>: {<span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"username"</span>: <span class="hljs-string">"user1"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"password1"</span>}, <span class="hljs-number">2</span>: {<span class="hljs-string">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"username"</span>: <span class="hljs-string">"user2"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"password2"</span>}, <span class="hljs-comment"># Add more users as needed</span> }

messages = []

<span class="hljs-comment"># Function to register a new user</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">register_user</span>(<span class="hljs-params">username, password</span>): <span class="hljs-comment"># Check if the user already exists</span> <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users.values(): <span class="hljs-keyword">if</span> user[<span class="hljs-string">'username'</span>] == username: <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>, <span class="hljs-string">"Username already exists"</span>

<span class="hljs-comment"># Generate a unique user ID</span>
user_id = <span class="hljs-built_in">max</span>(users.keys()) + <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> users <span class="hljs-keyword">else</span> <span class="hljs-number">1</span>

<span class="hljs-comment"># Create a new user and store in the user dictionary</span>
user = {<span class="hljs-string">"id"</span>: user_id, <span class="hljs-string">"username"</span>: username, <span class="hljs-string">"password"</span>: password}
users[user_id] = user

<span class="hljs-keyword">return</span> user, <span class="hljs-string">"User created successfully"</span>

<span class="hljs-comment"># Function to authenticate a user</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">login_user</span>(<span class="hljs-params">username, password</span>): <span class="hljs-comment"># Check if the user exists and the password is correct</span> <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users.values(): <span class="hljs-keyword">if</span> user[<span class="hljs-string">'username'</span>] == username <span class="hljs-keyword">and</span> user[<span class="hljs-string">'password'</span>] == password: <span class="hljs-keyword">return</span> user, <span class="hljs-string">"Login successful"</span>

<span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>, <span class="hljs-string">"Invalid username or password"</span>

<span class="hljs-comment"># Function to send a message</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">send_message</span>(<span class="hljs-params">sender_id, receiver_id, content</span>): <span class="hljs-comment"># Check if both sender and receiver exist</span> <span class="hljs-keyword">if</span> sender_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> users <span class="hljs-keyword">or</span> receiver_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> users: <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>, <span class="hljs-string">"Invalid sender or receiver"</span>

<span class="hljs-comment"># Create a new message and add it to the messages list</span>
message = {
    <span class="hljs-string">"sender_id"</span>: sender_id,
    <span class="hljs-string">"receiver_id"</span>: receiver_id,
    <span class="hljs-string">"content"</span>: content
}
messages.append(message)

<span class="hljs-keyword">return</span> message, <span class="hljs-string">"Message sent successfully"</span>

<span class="hljs-comment"># Test the functions</span> <span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: <span class="hljs-comment"># Test user registration</span> user1, msg1 = register_user(<span class="hljs-string">"user1"</span>, <span class="hljs-string">"password1"</span>) <span class="hljs-built_in">print</span>(msg1) <span class="hljs-comment"># Output: User created successfully</span>

user2, msg2 = register_user(<span class="hljs-string">"user2"</span>, <span class="hljs-string">"password2"</span>)
<span class="hljs-built_in">print</span>(msg2)  <span class="hljs-comment"># Output: User created successfully</span>

_, msg3 = register_user(<span class="hljs-string">"user1"</span>, <span class="hljs-string">"password123"</span>)
<span class="hljs-built_in">print</span>(msg3)  <span class="hljs-comment"># Output: Username already exists</span>

<span class="hljs-comment"># Test user login</span>
_, login_msg1 = login_user(<span class="hljs-string">"user1"</span>, <span class="hljs-string">"password1"</span>)
<span class="hljs-built_in">print</span>(login_msg1)  <span class="hljs-comment"># Output: Login successful</span>

_, login_msg2 = login_user(<span class="hljs-string">"user2"</span>, <span class="hljs-string">"password123"</span>)
<span class="hljs-built_in">print</span>(login_msg2)  <span class="hljs-comment"># Output: Invalid username or password</span>

<span class="hljs-comment"># Test sending a message</span>
message, send_msg = send_message(sender_id=user1[<span class="hljs-string">'id'</span>], receiver_id=user2[<span class="hljs-string">'id'</span>], content=<span class="hljs-string">"Hello, User2!"</span>)
<span class="hljs-built_in">print</span>(send_msg)  <span class="hljs-comment"># Output: Message sent successfully</span></pre></div><h1 id="6c06">API Design</h1><p id="2f16">User API:</p><ul><li><code>/users/register</code> (POST): Register a new user.</li><li><code>/users/login</code> (POST): Authenticate a user.</li><li><code>/users/{user_id}/friends</code> (GET): Get the list of user's friends/contacts.</li></ul><p id="0abb">Message API:</p><ul><li><code>/messages/send</code> (POST): Send a message to a user or group.</li><li><code>/messages/{message_id}</code> (GET): Get details of a specific message.</li><li><code>/messages/search</code> (GET): Search for messages based on content or timestamps.</li></ul><p id="5dcb">Group API:</p><ul><li><code>/groups/create</code> (POST): Create a new group chat.</li><li><code>/groups/{group_id}/add_member</code> (POST): Add a user to a group.</li><li><code>/groups/{group_id}/remove_member</code> (POST): Remove a user from a group.</li></ul><p id="a028">Push Notification API:</p><ul><li><code>/notifications/register</code> (POST): Register a device for push notifications.</li><li><code>/notifications/unregister</code> (POST): Unregister a device from push notifications.</li></ul><div id="fa2e"><pre>from flask <span class="hljs-keyword">import</span> Flask, request

app = Flask(name) instant_messenger = InstantMessenger()

User Registration API

<span class="hljs-meta">@app</span>.route(<span class="hljs-string">"/users/register"</span>, methods=[<span class="hljs-string">"POST"</span>]) def register_user(): <span class="hljs-keyword">data</span> = request.json user_id = str(len(instant_messenger.users) + <span class="hljs-number">1</span>) username = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">"username"</span>) password = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">"password"</span>) user = User(user_id, username, password) instant_messenger.add_user(user) <span class="hljs-keyword">return</span> { <span class="hljs-string">"user_id"</span>: user_id, <span class="hljs-string">"username"</span>: username, }, <span class="hljs-number">201</span>

Send Message API

<span class="hljs-meta">@app</span>.route(<span class="hljs-string">"/messages/send"</span>, methods=[<span class="hljs-string">"POST"</span>]) def send_message(): <span class="hljs-keyword">data</span> = request.json sender_id = <span class="hljs-

Options

keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">"sender_id"</span>) receiver_id = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">"receiver_id"</span>) content = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">"content"</span>) message = instant_messenger.send_message(sender_id, receiver_id, content) <span class="hljs-keyword">if</span> message: <span class="hljs-keyword">return</span> { <span class="hljs-string">"message_id"</span>: message.message_id, <span class="hljs-string">"sender"</span>: message.sender.username, <span class="hljs-string">"receiver"</span>: message.receiver.username, <span class="hljs-string">"content"</span>: message.content, }, <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User not found"</span>}, <span class="hljs-number">404</span>

Get Messages API

<span class="hljs-meta">@app</span>.route(<span class="hljs-string">"/messages/get/<user_id>"</span>, methods=[<span class="hljs-string">"GET"</span>]) def get_user_messages(user_id): user_messages = instant_messenger.get_user_messages(user_id) <span class="hljs-keyword">if</span> user_messages: messages_data = [] <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> user_messages: messages_data.append({ <span class="hljs-string">"message_id"</span>: message.message_id, <span class="hljs-string">"sender"</span>: message.sender.username, <span class="hljs-string">"receiver"</span>: message.receiver.username, <span class="hljs-string">"content"</span>: message.content, }) <span class="hljs-keyword">return</span> {<span class="hljs-string">"messages"</span>: messages_data}, <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User not found or no messages found"</span>}, <span class="hljs-number">404</span>

Run the Flask app

<span class="hljs-keyword">if</span> name == <span class="hljs-string">"main"</span>: app.run()</pre></div><h1 id="01e4">Complete Detailed Design</h1><p id="887e"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="1679"><i>Subscribe to youtube channel :</i></p><div id="64d4" class="link-block"> <a href="https://www.youtube.com/@ignito5917/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div> </div> </div> </a> </div><h1 id="6205">Complete Code implementation</h1><div id="03a6"><pre><span class="hljs-comment"># Real-Time Messaging</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">InstantMessenger</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.users = {} self.messages = []

<span class="hljs-keyword">def</span> <span class="hljs-title function_">send_message</span>(<span class="hljs-params">self, sender_id, receiver_id, content</span>):
    <span class="hljs-comment"># Check if both sender and receiver exist</span>
    <span class="hljs-keyword">if</span> sender_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.users <span class="hljs-keyword">or</span> receiver_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.users:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid sender or receiver"</span>

    <span class="hljs-comment"># Create a new message and add it to the messages list</span>
    message = {
        <span class="hljs-string">"sender_id"</span>: sender_id,
        <span class="hljs-string">"receiver_id"</span>: receiver_id,
        <span class="hljs-string">"content"</span>: content
    }
    self.messages.append(message)
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Message sent successfully"</span>

<span class="hljs-comment"># User Authentication</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">login_user</span>(<span class="hljs-params">username, password, users</span>): <span class="hljs-comment"># Check if the user exists and the password is correct</span> <span class="hljs-keyword">for</span> user_id, user <span class="hljs-keyword">in</span> users.items(): <span class="hljs-keyword">if</span> user[<span class="hljs-string">'username'</span>] == username <span class="hljs-keyword">and</span> user[<span class="hljs-string">'password'</span>] == password: <span class="hljs-keyword">return</span> user_id, <span class="hljs-string">"Login successful"</span>

<span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>, <span class="hljs-string">"Invalid username or password"</span>

<span class="hljs-comment"># Contacts and Friends List</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_contact</span>(<span class="hljs-params">user_id, contact_id, contacts</span>): <span class="hljs-comment"># Check if the user exists</span> <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> contacts: <span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid user"</span>

<span class="hljs-comment"># Add the contact</span>
contacts[user_id].add(contact_id)
<span class="hljs-keyword">return</span> <span class="hljs-string">"Contact added successfully"</span>

<span class="hljs-comment"># Presence Status</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">set_presence_status</span>(<span class="hljs-params">user_id, status, presence_status</span>): presence_status[user_id] = status <span class="hljs-keyword">return</span> <span class="hljs-string">"Presence status updated successfully"</span>

<span class="hljs-comment"># Message Delivery and Read Receipts</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">mark_message_delivered</span>(<span class="hljs-params">message_id, delivered_status, messages</span>): <span class="hljs-comment"># Check if the message exists</span> <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> messages: <span class="hljs-keyword">if</span> message[<span class="hljs-string">'message_id'</span>] == message_id: message[<span class="hljs-string">'delivered'</span>] = delivered_status <span class="hljs-keyword">return</span> <span class="hljs-string">"Message delivery status updated successfully"</span>

<span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid message ID"</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">mark_message_read</span>(<span class="hljs-params">message_id, read_status, messages</span>): <span class="hljs-comment"># Check if the message exists</span> <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> messages: <span class="hljs-keyword">if</span> message[<span class="hljs-string">'message_id'</span>] == message_id: message[<span class="hljs-string">'read'</span>] = read_status <span class="hljs-keyword">return</span> <span class="hljs-string">"Message read status updated successfully"</span>

<span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid message ID"</span>

<span class="hljs-comment"># Multimedia Sharing</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">share_multimedia</span>(<span class="hljs-params">sender_id, receiver_id, content, media_type, messages</span>): <span class="hljs-comment"># Check if both sender and receiver exist</span> <span class="hljs-keyword">if</span> sender_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.users <span class="hljs-keyword">or</span> receiver_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.users: <span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid sender or receiver"</span>

<span class="hljs-comment"># Create a new message and add it to the messages list</span>
message = {
    <span class="hljs-string">"sender_id"</span>: sender_id,
    <span class="hljs-string">"receiver_id"</span>: receiver_id,
    <span class="hljs-string">"content"</span>: content,
    <span class="hljs-string">"media_type"</span>: media_type
}
messages.append(message)
<span class="hljs-keyword">return</span> <span class="hljs-string">"Multimedia shared successfully"</span>

<span class="hljs-comment"># Push Notifications</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">send_push_notification</span>(<span class="hljs-params">user_id, notification, push_notifications</span>): push_notifications[user_id] = notification <span class="hljs-keyword">return</span> <span class="hljs-string">"Push notification sent successfully"</span>

<span class="hljs-comment"># Emojis and Stickers</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_emoji_sticker</span>(<span class="hljs-params">message_id, emoji_sticker, messages</span>): <span class="hljs-comment"># Check if the message exists</span> <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> messages: <span class="hljs-keyword">if</span> message[<span class="hljs-string">'message_id'</span>] == message_id: <span class="hljs-keyword">if</span> <span class="hljs-string">'emojis_stickers'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> message: message[<span class="hljs-string">'emojis_stickers'</span>] = [] message[<span class="hljs-string">'emojis_stickers'</span>].append(emoji_sticker) <span class="hljs-keyword">return</span> <span class="hljs-string">"Emoji/Sticker added successfully"</span>

<span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid message ID"</span>

<span class="hljs-comment"># Group Chats</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_group</span>(<span class="hljs-params">group_name, members, groups</span>): <span class="hljs-comment"># Generate a unique group ID</span> group_id = <span class="hljs-built_in">max</span>(groups.keys()) + <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> groups <span class="hljs-keyword">else</span> <span class="hljs-number">1</span>

<span class="hljs-comment"># Create the group and add it to the groups dictionary</span>
group = {<span class="hljs-string">"group_id"</span>: group_id, <span class="hljs-string">"group_name"</span>: group_name, <span class="hljs-string">"members"</span>: members}
groups[group_id] = group
<span class="hljs-keyword">return</span> <span class="hljs-string">"Group created successfully"</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_member_to_group</span>(<span class="hljs-params">group_id, member_id, groups</span>): <span class="hljs-comment"># Check if the group exists</span> <span class="hljs-keyword">if</span> group_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> groups: <span class="hljs-keyword">return</span> <span class="hljs-string">"Invalid group ID"</span>

<span class="hljs-comment"># Add the member to the group</span>
groups[group_id][<span class="hljs-string">"members"</span>].append(member_id)
<span class="hljs-keyword">return</span> <span class="hljs-string">"Member added to the group successfully"</span>

<span class="hljs-comment"># Message Search</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">search_messages</span>(<span class="hljs-params">query, messages</span>): <span class="hljs-comment"># Search for messages based on content or timestamps</span> search_results = [] <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> messages: <span class="hljs-keyword">if</span> query <span class="hljs-keyword">in</span> message[<span class="hljs-string">'content'</span>]: search_results.append(message)

<span class="hljs-keyword">return</span> search_results

<span class="hljs-comment"># End-to-End Encryption</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">encrypt_message</span>(<span class="hljs-params">message_content</span>): <span class="hljs-comment"># Implement encryption logic here (e.g., using cryptography libraries)</span> encrypted_content = <span class="hljs-string">"Encrypted: "</span> + message_content <span class="hljs-keyword">return</span> encrypted_content

<span class="hljs-keyword">def</span> <span class="hljs-title function_">decrypt_message</span>(<span class="hljs-params">encrypted_content</span>): <span class="hljs-comment"># Implement decryption logic here (e.g., using cryptography libraries)</span> decrypted_content = encrypted_content.replace(<span class="hljs-string">"Encrypted: "</span>, <span class="hljs-string">""</span>) <span class="hljs-keyword">return</span> decrypted_content

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: <span class="hljs-comment"># Usage example</span> im = InstantMessenger() im.users = { <span class="hljs-number">1</span>: {<span class="hljs-string">"username"</span>: <span class="hljs-string">"user1"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"password1"</span>}, <span class="hljs-number">2</span>: {<span class="hljs-string">"username"</span>: <span class="hljs-string">"user2"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"password2"</span>}, }

im.send_message(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-string">"Hello, User2!"</span>)  <span class="hljs-comment"># Output: "Message sent successfully"</span>

im.set_presence_status(<span class="hljs-number">1</span>, <span class="hljs-string">"online"</span>)  <span class="hljs-comment"># Output: "Presence status updated successfully"</span>
im.add_contact(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)  <span class="hljs-comment"># Output: "Contact added successfully"</span>

im.messages = [
    {<span class="hljs-string">"message_id"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"sender_id"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"receiver_id"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"Hello, User2!"</span>, <span class="hljs-string">"delivered"</span>: <span class="hljs-literal">True</span>, <span class="hljs-string">"read"</span>: <span class="hljs-literal">False</span>},
]

mark_message_delivered(<span class="hljs-number">1</span>, <span class="hljs-literal">True</span>)  <span class="hljs-comment"># Output: "Message delivery status updated successfully"</span>
mark_message_read(<span class="hljs-number">1</span>, <span class="hljs-literal">True</span>)  <span class="hljs-comment"># Output: "Message read status updated successfully"</span>

share_multimedia(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-string">"cat.jpg"</span>, <span class="hljs-string">"image"</span>)  <span class="hljs-comment"># Output: "Multimedia shared successfully"</span>

send_push_notification(<span class="hljs-number">2</span>, <span class="hljs-string">"You have a new message from User1!"</span>)  <span class="hljs-comment"># Output: "Push notification sent successfully"</span>

add_emoji_sticker(<span class="hljs-number">1</span>, <span class="hljs-string">"🙂"</span>)  <span class="hljs-comment"># Output: "Emoji/Sticker added successfully"</span>

groups = {}
create_group(<span class="hljs-string">"Family Group"</span>, [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], groups)  <span class="hljs-comment"># Output: "Group created successfully"</span>
add_member_to_group(<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, groups)  <span class="hljs-comment"># Output: "Member added to the group successfully"</span>

search_results = search_messages(<span class="hljs-string">"Hello"</span>, im.messages)  <span class="hljs-comment"># Output: [{'message_id': 1, 'sender_id': 1, 'receiver_id': 2, 'content': 'Hello, User2!', 'delivered': True, 'read': False}]</span>

encrypted_message = encrypt_message(<span class="hljs-string">"Hello, User2!"</span>)  <span class="hljs-comment"># Output: Encrypted message using encryption logic</span>
decrypted_message = decrypt_message(encrypted_message)  <span class="hljs-comment"># Output: "Hello, User2!"</span></pre></div><h1 id="c16c">System Design — Hacker News</h1><p id="3a23">We will be discussing in depth -</p><ul><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>What is Hacker News</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Important Features</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Scaling Requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Data Model — ER requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>High Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Basic Low Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>API Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Complete Detailed Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Code implementation</b></a></li></ul><figure id="15a8"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*_7mUD2ZBQUIhEQ_N.jpg"><figcaption>Pic credits : Pinterest</figcaption></figure><h1 id="fd8c">What is Hacker News</h1><p id="d385">Hacker News is a social news website that focuses on computer science, entrepreneurship, and technology-related topics. It was created by Paul Graham, the co-founder of Y Combinator, and is popular among developers, entrepreneurs, and tech enthusiasts. Users can submit links to interesting articles, ask questions, and participate in discussions by upvoting and commenting on posts.</p><h1 id="e020">Important Features</h1><ul><li>User Registration and Authentication: Users can create accounts and log in to participate in discussions and engage with the community.</li><li>Post Submission: Users can submit links to articles or ask questions, which will be visible to other users on the platform.</li><li>Voting System: Users can upvote or downvote posts and comments, which influences the visibility and ranking of the content.</li><li>Commenting System: Users can comment on posts and reply to other comments, promoting discussions and interactions.</li><li>Moderation: Implementing moderation features to control spam and maintain the quality of content.</li><li>User Profiles: Each user has a profile that showcases their submitted posts, comments, and voting history.</li><li>Real-time Updates: Users should see new posts, comments, and votes in real-time without the need for manual refreshing.</li></ul><h1 id="44f6">Scaling Requirements — Capacity Estimation</h1><p id="6a67">Small scale Simulation for Hacker News:</p><p id="cd63">Assumptions:</p><ul><li><i>Total number of users: 10 Million</i></li><li><i>Daily active users (DAU): 2 Million</i></li><li><i>Number of posts viewed by a user/day: 5</i></li><li><i>Total number of posts viewed per day: 10 Million posts/day</i></li><li><i>Since the system is read-heavy, let’s assume the read-to-write ratio to be 50:1.</i></li><li><i>Total number of posts submitted/day = 1/50 * 10 Million = 200,000 posts/day</i></li></ul><p id="73ee">Storage estimation:</p><ul><li>Average size of a post: 10 KB</li><li>Total Storage per day: 200,000 * 10 KB = 2,000,000 KB = 1.86 GB/day</li><li>For the next 3 years: 1.86 GB * 365 days * 3 years ≈ 2.04 TB</li><li>Requests per second: 10 Million / 3600 seconds * 24 hours ≈ 120 requests/second</li></ul><h1 id="38c9">Data Model — ER requirements</h1><ul><li>User: Stores user details like username, email, password, etc.</li><li>Post: Represents each submitted link/article with metadata like title, URL, timestamp, and vote count.</li><li>Comment: Stores comments made by users on posts, with references to the parent post and user who made the comment.</li><li>Vote: Records votes made by users on posts and comments.</li></ul><div id="9fdb"><pre><span class="hljs-keyword">User</span>

ID (<span class="hljs-keyword">Primary</span> Key) Username (<span class="hljs-keyword">Unique</span>) Email (<span class="hljs-keyword">Unique</span>) Password Registration <span class="hljs-type">Date</span> <span class="hljs-keyword">Last</span> Login <span class="hljs-type">Date</span>

Post

ID (<span class="hljs-keyword">Primary</span> Key) Title Content AuthorID (<span class="hljs-keyword">Foreign</span> Key <span class="hljs-keyword">referencing</span> User.ID) Creation <span class="hljs-type">Timestamp</span> <span class="hljs-keyword">Last</span> Updated <span class="hljs-type">Timestamp</span>

Comment

ID (<span class="hljs-keyword">Primary</span> Key) PostID (<span class="hljs-keyword">Foreign</span> Key <span class="hljs-keyword">referencing</span> Post.ID) Parent Comment ID (<span class="hljs-keyword">Foreign</span> Key <span class="hljs-keyword">referencing</span> Comment.ID, <span class="hljs-keyword">for</span> replies) AuthorID (<span class="hljs-keyword">Foreign</span> Key <span class="hljs-keyword">referencing</span> User.ID) Content Creation <span class="hljs-type">Timestamp</span> <span class="hljs-keyword">Last</span> Updated <span class="hljs-type">Timestamp</span>

Vote

ID (<span class="hljs-keyword">Primary</span> Key) UserID (<span class="hljs-keyword">Foreign</span> Key <span class="hljs-keyword">referencing</span> User.ID) Target Type (Post <span class="hljs-keyword">or</span> Comment) Target ID (<span class="hljs-keyword">Foreign</span> Key <span class="hljs-keyword">referencing</span> Post.ID <span class="hljs-keyword">or</span> Comment.ID) Vote Type (Upvote <span class="hljs-keyword">or</span> Downvote) Creation <span class="hljs-type">Timestamp</span></pre></div><h1 id="64cd">High Level Design</h1><ul><li>Web Servers: Responsible for handling incoming HTTP requests from users’ browsers and serving HTML pages.</li><li>Application Servers: Process the business logic, handle authentication, and interact with the database.</li><li>Database Servers: Store user data, posts, comments, votes, etc.</li><li>Caching Layer: Stores frequently accessed data to reduce database load.</li><li>Content Delivery Network (CDN): Serves static content like images, CSS, and JavaScript for faster delivery.</li><li>Background Workers: Perform asynchronous tasks such as sending emails and processing notifications.</li><li>Load Balancing: Distributing incoming traffic across multiple servers to prevent overload on any one server.</li><li>Caching: Implementing caching mechanisms to reduce database and server load.</li><li>Database Scaling: Utilizing sharding, partitioning, or NoSQL solutions to handle increasing amounts of data.</li><li>Content Delivery Network (CDN): Using a CDN to serve static assets and reduce latency for users across the globe.</li><li>Asynchronous Processing: Offloading resource-intensive tasks to background workers to maintain responsiveness.</li></ul><p id="8963"><b>Assumptions</b>:</p><ul><li>There will be more reads than writes, so the system is read-heavy.</li><li>Users should have real-time updates on posts and comments.</li><li>The system needs to be highly available and scalable to handle millions of users.</li></ul><p id="c402"><b>Main Components:</b></p><ol><li>Web Servers: Handle incoming HTTP requests from users’ browsers.</li><li>Application Servers: Perform business logic, handle authentication, and process user requests.</li><li>Database Servers: Store user data, posts, comments, and votes.</li><li>Cache Servers: Cache frequently accessed data to reduce database load.</li><li>Load Balancer: Distributes incoming traffic across multiple servers to ensure even distribution.</li><li>Content Delivery Network (CDN): Serves static assets for faster delivery to users across the globe.</li></ol><p id="1c4b"><b>Services for Hacker News System:</b></p><p id="3b47">User Service:</p><ul><li>Register User: Allows users to create accounts and store user information in the database.</li><li>Login/Authentication: Handles user login and authentication using secure mechanisms.</li><li>User Profile: Fetches and displays user profiles with their submitted posts, comments, and voting history.</li></ul><p id="592a">Post Service:</p><ul><li>Create Post: Allows users to submit new posts and store post information in the database.</li><li>View Post: Retrieves and displays posts with comments, votes, and author information.</li><li>Update Post: Enables users to edit and update their posts.</li></ul><p id="84a3">Comment Service:</p><ul><li>Add Comment: Allows users to comment on posts and store comment information in the database.</li><li>Reply to Comment: Allows users to reply to existing comments and store the reply information.</li></ul><p id="b21c">Vote Service:</p><ul><li>Upvote/Downvote Post: Allows users to upvote or downvote posts and store vote information.</li><li>Upvote/Downvote Comment: Allows users to upvote or downvote comments and store vote information.</li></ul><p id="9d52">Feed Generation Service:</p><ul><li>Generates personalized news feeds for users based on the posts of users they follow.</li><li>Utilizes ranking algorithms to prioritize relevant, popular, and recent posts.</li></ul><p id="010c">Real-time Updates Service:</p><ul><li>Provides real-time updates to users for new posts, comments, and votes.</li><li>Utilizes WebSockets or similar technologies to push updates instantly.</li></ul><p id="c996">Moderation Service:</p><ul><li>Implements moderation features to control spam, offensive content, and maintain content quality.</li></ul><h1 id="ca2b">Basic Low Level Design</h1><p id="be44">User Entity:</p><ul><li>userId: Unique identifier for each user.</li><li>username: User’s username.</li><li>password: User’s password.</li><li>otherUserAttributes: Any other attributes related to the user, e.g., email, registration date, etc.</li></ul><p id="b94c">Post Entity:</p><ul><li>postId: Unique identifier for each post.</li><li>user: Reference to the User entity, representing the author of the post.</li><li>caption: The caption or text associated with the post.</li><li>otherPostAttributes: Any other attributes related to the post, e.g., creation timestamp, likes count, etc.</li></ul><p id="1829">Comment Entity:</p><ul><li>commentId: Unique identifier for each comment.</li><li>post: Reference to the Post entity that the comment belongs to.</li><li>user: Reference to the User entity, representing the author of the comment.</li><li>content: The content or text of the comment.</li><li>otherCommentAttributes: Any other attributes related to the comment, e.g., creation timestamp, likes count, etc.</li></ul><div id="0a29"><pre>from flask <span class="hljs-keyword">import</span> Flask, request, jsonify

app = Flask(name)

Dummy <span class="hljs-keyword">in</span>-memory <span class="hljs-keyword">data</span> storage (simplified <span class="hljs-keyword">for</span> demonstration)

users = [] posts = [] comments = [] votes = []

User Service

def register_user(username, email, password): new_user = {<span class="hljs-string">'username'</span>: username, <span class="hljs-string">'email'</span>: email, <span class="hljs-string">'password'</span>: password, <span class="hljs-string">'posts'</span>: [], <span class="hljs-string">'comments'</span>: []} users.append(new_user) <span class="hljs-keyword">return</span> new_user

def get_user_by_username(username): <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users: <span class="hljs-keyword">if</span> user[<span class="hljs-string">'username'</span>] == username: <span class="hljs-keyword">return</span> user <span class="hljs-keyword">return</span> None

<span class="hljs-meta">@app</span>.route(<span class="hljs-string">'/api/register'</span>, methods=[<span class="hljs-string">'POST'</span>]) def api_register_user(): <span class="hljs-keyword">data</span> = request.json username = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'username'</span>) email = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'email'</span>) password = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'password'</span>)

<span class="hljs-keyword">if</span> not username or not email or not password:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'All fields are required.'</span>}), <span class="hljs-number">400</span>

<span class="hljs-keyword">if</span> get_user_by_username(username):
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Username already exists.'</span>}), <span class="hljs-number">409</span>

new_user = register_user(username, email, password)
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Registration successful.'</span>, <span class="hljs-string">'user'</span>: new_user}), <span class="hljs-number">201</span>

Post Service

def create_post(author_id, title, content): new_post = {<span class="hljs-string">'title'</span>: title, <span class="hljs-string">'content'</span>: content, <span class="hljs-string">'author_id'</span>: author_id, <span class="hljs-string">'comments'</span>: []} posts.append(new_post) user = get_user_by_id(author_id) user[<span class="hljs-string">'posts'</span>].append(new_post) <span class="hljs-keyword">return</span> new_post

def get_post_by_id(post_id): <span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts: <span class="hljs-keyword">if</span> post[<span class="hljs-string">'id'</span>] == post_id: <span class="hljs-keyword">return</span> post <span class="hljs-keyword">return</span> None

<span class="hljs-meta">@app</span>.route(<span class="hljs-string">'/api/posts'</span>, methods=[<span class="hljs-string">'POST'</span>]) def api_create_post(): <span class="hljs-keyword">data</span> = request.json author_id = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'author_id'</span>) title = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'title'</span>) content = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'content'</span>)

<span class="hljs-keyword">if</span> not author_id or not title or not content:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Author ID, title, and content are required.'</span>}), <span class="hljs-number">400</span>

user = get_user_by_id(author_id)
<span class="hljs-keyword">if</span> not user:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'User not found.'</span>}), <span class="hljs-number">404</span>

new_post = create_post(author_id, title, content)
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Post created successfully.'</span>, <span class="hljs-string">'post'</span>: new_post}), <span class="hljs-number">201</span>

Comment Service

def add_comment(post_id, author_id, content): post = get_post_by_id(post_id) <span class="hljs-keyword">if</span> not post: <span class="hljs-keyword">return</span> None

new_comment = {<span class="hljs-string">'post_id'</span>: post_id, <span class="hljs-string">'author_id'</span>: author_id, <span class="hljs-string">'content'</span>: content}
comments.append(new_comment)
post[<span class="hljs-string">'comments'</span>].append(new_comment)

<span class="hljs-keyword">return</span> new_comment

def get_comment_by_id(comment_id): <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> comments: <span class="hljs-keyword">if</span> comment[<span class="hljs-string">'id'</span>] == comment_id: <span class="hljs-keyword">return</span> comment <span class="hljs-keyword">return</span> None

<span class="hljs-meta">@app</span>.route(<span class="hljs-string">'/api/comments'</span>, methods=[<span class="hljs-string">'POST'</span>]) def api_add_comment(): <span class="hljs-keyword">data</span> = request.json post_id = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'post_id'</span>) author_id = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'author_id'</span>) content = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'content'</span>)

<span class="hljs-keyword">if</span> not post_id or not author_id or not content:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Post ID, author ID, and content are required.'</span>}), <span class="hljs-number">400</span>

post = get_post_by_id(post_id)
<span class="hljs-keyword">if</span> not post:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Post not found.'</span>}), <span class="hljs-number">404</span>

user = get_user_by_id(author_id)
<span class="hljs-keyword">if</span> not user:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'User not found.'</span>}), <span class="hljs-number">404</span>

new_comment = add_comment(post_id, author_id, content)
<span class="hljs-keyword">if</span> not new_comment:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Failed to add comment.'</span>}), <span class="hljs-number">500</span>

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Comment added successfully.'</span>, <span class="hljs-string">'comment'</span>: new_comment}), <span class="hljs-number">201</span>

Vote Service

def vote(voter_id, target_type, target_id, vote_type): new_vote = {<span class="hljs-string">'voter_id'</span>: voter_id, <span class="hljs-string">'target_type'</span>: target_type, <span class="hljs-string">'target_id'</span>: target_id, <span class="hljs-string">'vote_type'</span>: vote_type} votes.append(new_vote) <span class="hljs-keyword">return</span> new_vote

<span class="hljs-meta">@app</span>.route(<span class="hljs-string">'/api/votes'</span>, methods=[<span class="hljs-string">'POST'</span>]) def api_vote(): <span class="hljs-keyword">data</span> = request.json voter_id = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'voter_id'</span>) target_type = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'target_type'</span>) target_id = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'target_id'</span>) vote_type = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'vote_type'</span>)

<span class="hljs-keyword">if</span> not voter_id or not target_type or not target_id or not vote_type:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Voter ID, target type, target ID, and vote type are required.'</span>}), <span class="hljs-number">400</span>

new_vote = vote(voter_id, target_type, target_id, vote_type)
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Vote recorded successfully.'</span>, <span class="hljs-string">'vote'</span>: new_vote}), <span class="hljs-number">201</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()</pre></div><h1 id="404b">API Design</h1><ul><li>User API: Endpoints for user registration, authentication, and profile management.</li><li>Post API: Endpoints for submitting, retrieving, and voting on posts.</li><li>Comment API: Endpoints for commenting on posts and replying to comments.</li><li>Moderation API: Endpoints for moderation actions, such as flagging or reporting content.</li><li>Real-time API: Implement WebSocket or similar technology for real-time updates.</li></ul><div id="b93f"><pre>from flask <span class="hljs-keyword">import</span> Flask, Blueprint, request, jsonify

app = Flask(name) user_api = Blueprint(<span class="hljs-string">'user_api'</span>, name) post_api = Blueprint(<span class="hljs-string">'post_api'</span>, name)

In-memory <span class="hljs-keyword">data</span> storage

users = [] posts = []

Helper function to find a user <span class="hljs-keyword">by</span> their username

def find_user_by_username(username): <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users: <span class="hljs-keyword">if</span> user[<span class="hljs-string">'username'</span>] == username: <span class="hljs-keyword">return</span> user <span class="hljs-keyword">return</span> None

<span class="hljs-meta">@user_api</span>.route(<span class="hljs-string">'/register'</span>, methods=[<span class="hljs-string">'POST'</span>]) def register_user(): <span class="hljs-keyword">data</span> = request.json username = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'username'</span>) email = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'email'</span>) password = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'password'</span>)

# Basic input validation
<span class="hljs-keyword">if</span> not username or not email or not password:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'All fields are required.'</span>}), <span class="hljs-number">400</span>

# Check <span class="hljs-keyword">if</span> the username already exists
<span class="hljs-keyword">if</span> find_user_by_username(username):
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Username already exists.'</span>}), <span class="hljs-number">409</span>

# Create a new user
new_user = {<span class="hljs-string">'username'</span>: username, <span class="hljs-string">'email'</span>: email, <span class="hljs-string">'password'</span>: password}
users.append(new_user)

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Registration successful.'</span>}), <span class="hljs-number">201</span>

<span class="hljs-meta">@post_api</span>.route(<span class="hljs-string">'/submit'</span>, methods=[<span class="hljs-string">'POST'</span>]) def submit_post(): <span class="hljs-keyword">data</span> = request.json title = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'title'</span>) url = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'url'</span>) username = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'username'</span>) # In a real-world scenario, <span class="hljs-keyword">this</span> would be obtained from user authentication.

# Basic input validation
<span class="hljs-keyword">if</span> not title or not url or not username:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Title, URL, and username are required.'</span>}), <span class="hljs-number">400</span>

# Check <span class="hljs-keyword">if</span> the user exists
user = find_user_by_username(username)
<span class="hljs-keyword">if</span> not user:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'User not found.'</span>}), <span class="hljs-number">404</span>

# Create a new post
new_post = {<span class="hljs-string">'title'</span>: title, <span class="hljs-string">'url'</span>: url, <span class="hljs-string">'username'</span>: username, <span class="hljs-string">'votes'</span>: <span class="hljs-number">0</span>}
posts.append(new_post)

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Post submitted successfully.'</span>}), <span class="hljs-number">201</span>

<span class="hljs-meta">@post_api</span>.route(<span class="hljs-string">'/vote'</span>, methods=[<span class="hljs-string">'POST'</span>]) def vote_post(): <span class="hljs-keyword">data</span> = request.json post_title = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'post_title'</span>) username = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'username'</span>) # In a real-world scenario, <span class="hljs-keyword">this</span> would be obtained from user authentication. vote_type = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'vote_type'</span>) # <span class="hljs-string">'upvote'</span> or <span class="hljs-string">'downvote'</span>

# Basic input validation
<span class="hljs-keyword">if</span> not post_title or not username or vote_type not <span class="hljs-keyword">in</span> [<span class="hljs-string">'upvote'</span>, <span class="hljs-string">'downvote'</span>]:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Invalid input data.'</span>}), <span class="hljs-number">400</span>

# Find the post
<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-keyword">if</span> post[<span class="hljs-string">'title'</span>] == post_title:
        # Check <span class="hljs-keyword">if</span> the user exists
        user = find_user_by_username(username)
        <span class="hljs-keyword">if</span> not user:
            <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'User not found.'</span>}), <span class="hljs-number">404</span>

        # Upvote or downvote the post
        <span class="hljs-keyword">if</span> vote_type == <span class="hljs-string">'upvote'</span>:
            post[<span class="hljs-string">'votes'</span>] += <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            post[<span class="hljs-string">'votes'</span>] -= <span class="hljs-number">1</span>

        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Vote recorded successfully.'</span>}), <span class="hljs-number">200</span>

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Post not found.'</span>}), <span class="hljs-number">404</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.register_blueprint(user_api, url_prefix=<span class="hljs-string">'/api/users'</span>) app.register_blueprint(post_api, url_prefix=<span class="hljs-string">'/api/posts'</span>) app.run()</pre></div><h1 id="7e79">Complete Detailed Design</h1><p id="f342"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="7a14"><i>Subscribe to youtube channel :</i></p><div id="e439" class="link-block"> <a href="https://www.youtube.com/@ignito5917/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div> </div> </div> </a> </div><h1 id="13fd">Complete Code implementation</h1><div id="3134"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify

app = Flask(name)

<span class="hljs-comment"># In-memory data storage (simplified for demonstration)</span> users = [] posts = [] comments = []

<span class="hljs-comment"># User Registration and Authentication</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/register'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">register_user</span>(): data = request.json username = data.get(<span class="hljs-string">'username'</span>) password = data.get(<span class="hljs-string">'password'</span>)

<span class="hljs-comment"># Basic input validation</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> username <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> password:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'All fields are required.'</span>}), <span class="hljs-number">400</span>

<span class="hljs-comment"># Check if the username already exists</span>
<span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users:
    <span class="hljs-keyword">if</span> user[<span class="hljs-string">'username'</span>] == username:
        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Username already exists.'</span>}), <span class="hljs-number">409</span>

new_user = {<span class="hljs-string">'username'</span>: username, <span class="hljs-string">'password'</span>: password, <span class="hljs-string">'posts'</span>: [], <span class="hljs-string">'comments'</span>: [], <span class="hljs-string">'votes'</span>: {}}
users.append(new_user)

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Registration successful.'</span>}), <span class="hljs-number">201</span>

<span class="hljs-comment"># Post Submission</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/submit_post'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">submit_post</span>(): data = request.json title = data.get(<span class="hljs-string">'title'</span>) content = data.get(<span class="hljs-string">'content'</span>) username = data.get(<span class="hljs-string">'username'</span>)

<span class="hljs-comment"># Basic input validation</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> title <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> content <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> username:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Title, content, and username are required.'</span>}), <span class="hljs-number">400</span>

<span class="hljs-comment"># Find the user</span>
user = <span class="hljs-literal">None</span>
<span class="hljs-keyword">for</span> u <span class="hljs-keyword">in</span> users:
    <span class="hljs-keyword">if</span> u[<span class="hljs-string">'username'</span>] == username:
        user = u
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'User not found.'</span>}), <span class="hljs-number">404</span>

new_post = {<span class="hljs-string">'title'</span>: title, <span class="hljs-string">'content'</span>: content, <span class="hljs-string">'author'</span>: username, <span class="hljs-string">'votes'</span>: <span class="hljs-number">0</span>, <span class="hljs-string">'comments'</span>: []}
posts.append(new_post)
user[<span class="hljs-string">'posts'</span>].append(new_post)

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Post submitted successfully.'</span>}), <span class="hljs-number">201</span>

<span class="hljs-comment"># Voting System</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/vote'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">vote_post</span>(): data = request.json post_id = data.get(<span class="hljs-string">'post_id'</span>) username = data.get(<span class="hljs-string">'username'</span>) vote_type = data.get(<span class="hljs-string">'vote_type'</span>) <span class="hljs-comment"># 'upvote' or 'downvote'</span>

<span class="hljs-comment"># Basic input validation</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> post_id <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> username <span class="hljs-keyword">or</span> vote_type <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'upvote'</span>, <span class="hljs-string">'downvote'</span>]:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Invalid input data.'</span>}), <span class="hljs-number">400</span>

<span class="hljs-comment"># Find the post</span>
post = <span class="hljs-literal">None</span>
<span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> posts:
    <span class="hljs-keyword">if</span> p[<span class="hljs-string">'id'</span>] == post_id:
        post = p
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> post:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Post not found.'</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Find the user</span>
user = <span class="hljs-literal">None</span>
<span class="hljs-keyword">for</span> u <span class="hljs-keyword">in</span> users:
    <span class="hljs-keyword">if</span> u[<span class="hljs-string">'username'</span>] == username:
        user = u
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'User not found.'</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Apply the vote to the post</span>
<span class="hljs-keyword">if</span> vote_type == <span class="hljs-string">'upvote'</span>:
    post[<span class="hljs-string">'votes'</span>] += <span class="hljs-number">1</span>
<span class="hljs-keyword">else</span>:
    post[<span class="hljs-string">'votes'</span>] -= <span class="hljs-number">1</span>

<span class="hljs-comment"># Store the vote in the user's vote history</span>
user[<span class="hljs-string">'votes'</span>][post_id] = vote_type

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Vote recorded successfully.'</span>}), <span class="hljs-number">200</span>

<span class="hljs-comment"># Commenting System</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/comment'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_comment</span>(): data = request.json post_id = data.get(<span class="hljs-string">'post_id'</span>) username = data.get(<span class="hljs-string">'username'</span>) content = data.get(<span class="hljs-string">'content'</span>)

<span class="hljs-comment"># Basic input validation</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> post_id <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> username <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> content:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Post ID, username, and content are required.'</span>}), <span class="hljs-number">400</span>

<span class="hljs-comment"># Find the post</span>
post = <span class="hljs-literal">None</span>
<span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> posts:
    <span class="hljs-keyword">if</span> p[<span class="hljs-string">'id'</span>] == post_id:
        post = p
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> post:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Post not found.'</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Find the user</span>
user = <span class="hljs-literal">None</span>
<span class="hljs-keyword">for</span> u <span class="hljs-keyword">in</span> users:
    <span class="hljs-keyword">if</span> u[<span class="hljs-string">'username'</span>] == username:
        user = u
        <span class="hljs-keyword">break</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'User not found.'</span>}), <span class="hljs-number">404</span>

new_comment = {<span class="hljs-string">'content'</span>: content, <span class="hljs-string">'author'</span>: username, <span class="hljs-string">'votes'</span>: <span class="hljs-number">0</span>}
comments.append(new_comment)
post[<span class="hljs-string">'comments'</span>].append(new_comment)
user[<span class="hljs-string">'comments'</span>].append(new_comment)

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Comment added successfully.'</span>}), <span class="hljs-number">201</span>

<span class="hljs-comment"># Moderation (not implemented in this simplified version)</span>

<span class="hljs-comment"># User Profiles</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/user_profile/<username>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_profile</span>(<span class="hljs-params">username</span>): <span class="hljs-comment"># Find the user</span> user = <span class="hljs-literal">None</span> <span class="hljs-keyword">for</span> u <span class="hljs-keyword">in</span> users: <span class="hljs-keyword">if</span> u[<span class="hljs-string">'username'</span>] == username: user = u <span class="hljs-keyword">break</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'User not found.'</span>}), <span class="hljs-number">404</span>

<span class="hljs-keyword">return</span> jsonify(user)

<span class="hljs-comment"># Real-time Updates (not implemented in this simplified version)</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()</pre></div><h1 id="1296">System Design — Facebook Timeline Function</h1><p id="87fb">We will be discussing in depth -</p><ul><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>What is Facebook Timeline Function</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Important Features</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Scaling Requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Data Model — ER requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>High Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Basic Low Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>API Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Complete Detailed Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Code implementation</b></a></li></ul><figure id="b574"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*_1YjrC-kUFTmmZ9s.jpg"><figcaption>Pic credits : Pinterest</figcaption></figure><h1 id="0177">What is Facebook Timeline Function</h1><p id="b9ac">Facebook Timeline is a feature that allows users to create a chronological profile of their life events, activities, and shared content on the Facebook platform. It presents a personalized history of a user’s posts, photos, videos, and other interactions, providing an engaging way for users to reminisce and share their life journey with friends and followers.</p><h1 id="e908">Important Features</h1><ol><li>Chronological Ordering: Facebook Timeline displays content in reverse-chronological order, showing the most recent events first.</li><li>Multimedia Content: Users can add various types of media to their timeline, including photos, videos, and shared posts.</li><li>Life Events: Users can highlight significant life events, such as birthdays, graduations, new jobs, and relationships.</li><li>Privacy Controls: Facebook Timeline offers privacy settings that allow users to control who can view specific posts and events on their timeline.</li><li>Activity Log: Users can review and manage all their past activities on Facebook through the activity log, ensuring transparency and control over their data.</li><li>Featured Posts: The ability to pin or feature important posts or life events to make them more prominent on the timeline.</li></ol><h1 id="c915">Scaling Requirements — Capacity Estimation</h1><p id="f2cc">For the sake of simplicity, I’ll consider a smaller user base:</p><ul><li><i>Total number of users: 100,000</i></li><li><i>Daily active users (DAU): 30,000</i></li><li><i>Number of posts by user/day: 5</i></li><li><i>Total number of posts per day: 150,000 posts/day</i></li></ul><p id="c1a4">Since the system is read-heavy, let’s assume the read-to-write ratio is 50:1.</p><ul><li>Total number of posts read per day: 150,000 * 50 = 7,500,000 reads/day</li><li>Total number of posts written per day: 150,000 writes/day</li></ul><p id="afa7">Let’s estimate the storage:</p><ul><li>On average, each post size is 1 MB.</li><li>Total storage per day: 150,000 * 1 MB = 150 GB/day</li><li>For the next 3 years: 150 GB * 365 * 3 = 164.25 TB</li></ul><p id="01ee">Requests per second:</p><ul><li>Posts read per second: 7,500,000 / (3600 seconds * 24 hours) ≈ 87 requests/second</li><li>Posts written per second: 150,000 / (3600 seconds * 24 hours) ≈ 2 requests/second</li></ul><div id="f6eb"><pre><span class="hljs-keyword">import</span> random <span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime, timedelta

<span class="hljs-keyword">class</span> <span class="hljs-title class_">FacebookTimeline</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.posts = {}

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_post</span>(<span class="hljs-params">self, user_id, content</span>):
    <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.posts:
        self.posts[user_id] = []
    post = {
        <span class="hljs-string">"post_id"</span>: <span class="hljs-built_in">len</span>(self.posts[user_id]) + <span class="hljs-number">1</span>,
        <span class="hljs-string">"content"</span>: content,
        <span class="hljs-string">"timestamp"</span>: datetime.now()
    }
    self.posts[user_id].append(post)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_timeline</span>(<span class="hljs-params">self, user_id</span>):
    <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">in</span> self.posts:
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">sorted</span>(self.posts[user_id], key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-string">"timestamp"</span>], reverse=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> []

<span class="hljs-keyword">if</span> name == <span class="hljs-string">"main"</span>: facebook = FacebookTimeline() users = [<span class="hljs-string">f"user<span class="hljs-subst">{i}</span>"</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, <span class="hljs-number">100001</span>)]

<span class="hljs-comment"># Simulating daily activity</span>
<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">30_000</span>):
    user_id = random.choice(users)
    num_posts = random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>)
    <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(num_posts):
        content = <span class="hljs-string">f"This is post <span class="hljs-subst">{random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">1000</span>)}</span> by <span class="hljs-subst">{user_id}</span>"</span>
        facebook.add_post(user_id, content)

<span class="hljs-comment"># Get timeline for a random user</span>
user_id = random.choice(users)
timeline = facebook.get_timeline(user_id)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f"Timeline for user <span class="hljs-subst">{user_id}</span>:"</span>)
<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> timeline:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Post <span class="hljs-subst">{post[<span class="hljs-string">'post_id'</span>]}</span>: <span class="hljs-subst">{post[<span class="hljs-string">'content'</span>]}</span> (<span class="hljs-subst">{post[<span class="hljs-string">'timestamp'</span>]}</span>)"</span>)</pre></div><h1 id="c634">Data Model — ER requirements</h1><ol><li>User: Represents registered users with attributes like UserID, Name, Email, PasswordHash, etc.</li><li>Timeline: Each user has a corresponding Timeline with attributes like TimelineID, UserID (foreign key), CreationDate, LastUpdateDate, etc.</li><li>Posts: Represents individual posts with attributes like PostID, UserID (foreign key), Content, MediaType, PostDate, etc.</li><li>LifeEvents: Stores user life events with attributes like EventID, UserID (foreign key), EventType, EventDate, Description, etc.</li></ol><div id="e0e8"><pre><span class="hljs-symbol">User:</span>

userId (unique identifier <span class="hljs-keyword">for</span> users) username (user<span class="hljs-comment">'s display name)</span> email (user<span class="hljs-comment">'s email address)</span> password (user<span class="hljs-comment">'s password)</span> other attributes (e.g., profile picture, bio, etc.)

<span class="hljs-symbol">Post:</span>

postId (unique identifier <span class="hljs-keyword">for</span> posts) userId (foreign <span class="hljs-keyword">key</span> <span class="hljs-keyword">from</span> the User table <span class="hljs-keyword">to</span> identify the post owner) content (<span class="hljs-keyword">text</span> <span class="hljs-built_in">or</span> media content <span class="hljs-keyword">of</span> the post) timestamp (timestamp indicating <span class="hljs-keyword">when</span> the post was created) other attributes (e.g., location, likes count, comments count, etc.)

<span class="hljs-symbol">Follow:</span>

followerId (foreign <span class="hljs-keyword">key</span> <span class="hljs-keyword">from</span> the User table <span class="hljs-keyword">to</span> identify the follower) followeeId (foreign <span class="hljs-keyword">key</span> <span class="hljs-keyword">from</span> the User table <span class="hljs-keyword">to</span> identify the user being followed)

<span class="hljs-symbol">Like:</span>

likeId (unique identifier <span class="hljs-keyword">for</span> likes) userId (foreign <span class="hljs-keyword">key</span> <span class="hljs-keyword">from</span> the User table <span class="hljs-keyword">to</span> identify the user who liked the post) postId (foreign <span class="hljs-keyword">key</span> <span class="hljs-keyword">from</span> the Post table <span class="hljs-keyword">to</span> identify the post that was liked) timestamp (timestamp indicating <span class="hljs-keyword">when</span> the <span class="hljs-built_in">like</span> was added)

<span class="hljs-symbol">Comment:</span>

commentId (unique identifier <span class="hljs-keyword">for</span> comments) userId (foreign <span class="hljs-keyword">key</span> <span class="hljs-keyword">from</span> the User table <span class="hljs-keyword">to</span> identify the user who commented) postId (foreign <span class="hljs-keyword">key</span> <span class="hljs-keyword">from</span> the Post table <span class="hljs-keyword">to</span> identify the post <span class="hljs-keyword">on</span> which the comment was made) content (<span class="hljs-keyword">text</span> content <span class="hljs-keyword">of</span> the comment) timestamp (timestamp indicating <span class="hljs-keyword">when</span> the comment was added)</pre></div><h1 id="1868">High Level Design</h1><ol><li>High User Traffic: Facebook has billions of active users, so the system must handle a massive number of concurrent requests.</li><li>Storage: As users add multimedia content to their timelines, the system needs to handle and efficiently store large amounts of data.</li><li>High Availability: The Timeline should be accessible and responsive at all times, even during peak usage.</li><li>Data Consistency: Ensuring consistency across distributed servers is crucial to maintaining accurate timelines.</li><li>Frontend: Responsible for user interactions, rendering the timeline UI, and making API calls to the backend.</li><li>Web Servers: Handle user requests from the frontend, perform authentication, and route requests to appropriate backend services.</li><li>Load Balancer: Distributes incoming requests across multiple web servers to ensure optimal utilization and availability.</li><li>Backend Services: Consist of various microservices, including User Service, Timeline Service, Post Service, Life Event Service, etc.</li><li>Database Servers: Store user data, posts, and timeline information in a distributed and scalable database.</li><li>Caching Layer: Employ caching mechanisms to reduce database load and improve response times for frequently accessed content.</li></ol><p id="2650"><b>Assumptions</b>:</p><ul><li>The system is read-heavy, as users spend more time viewing posts than creating them.</li><li>There will be more reads than writes, so we need a read-heavy system with more replicas for read operations.</li><li>Horizontal scaling will be used for handling increased traffic.</li><li>Services should be highly available.</li><li>Latency should be low for an optimal user experience.</li><li>Consistency is essential for ensuring users see the latest content.</li><li>Caching mechanisms will be used to reduce database load and improve response times.</li></ul><p id="140a"><b>Main Components and Services:</b></p><ol><li>Mobile Client: Represents users accessing the Facebook Timeline platform through mobile devices.</li><li>Application Servers: Handle read, write, and notification requests from the mobile clients.</li><li>Load Balancer: Routes and directs incoming requests to the appropriate servers based on designated services.</li><li>Cache (Memcache or Redis): Used to cache frequently accessed data and reduce database load.</li><li>CDN: Improves latency and throughput by caching and serving static content like images.</li><li>Database: Stores user data, posts, likes, and comments.</li></ol><p id="9966"><b>Services:</b></p><p id="e189">User Service:</p><ul><li>Register new users with a unique UserID.</li><li>Authenticate user login using email and password.</li></ul><p id="8593">Post Service:</p><ul><li>Allow users to create new posts and associate them with their UserID.</li><li>Retrieve posts for a user’s timeline based on their UserID.</li><li>Support post updates and deletions.</li></ul><p id="caca">Like Service:</p><ul><li>Allow users to like posts and store their UserID and the PostID they liked.</li><li>Provide functionality to unlike a post if required.</li></ul><p id="f26a">Comment Service:</p><ul><li>Allow users to add comments to posts and store the CommentID, UserID, PostID, and comment text.</li><li>Support comment replies and nested comments.</li></ul><p id="7bcb">Follow Service:</p><ul><li>Enable users to follow other users by storing their UserID and the UserID they are following.</li></ul><p id="76cd">Feed Generation Service:</p><ul><li>Generate the user’s timeline feed by fetching recent posts from users they follow.</li><li>Sort and rank posts based on activity (likes, comments) to provide a relevant and engaging feed.</li></ul><h1 id="dbc8">Basic Low Level Design</h1><div id="b151"><pre><span class="hljs-keyword">import</span> random <span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime, timedelta

<span class="hljs-keyword">class</span> <span class="hljs-title class_">FacebookTimeline</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.users = {} self.posts = {} self.likes = {} self.comments = {}

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_user</span>(<span class="hljs-params">self, user_id, username, email, password</span>):
    self.users[user_id] = {
        <span class="hljs-string">"username"</span>: username,
        <span class="hljs-string">"email"</span>: email,
        <span class="hljs-string">"password"</span>: password
    }

<span class="hljs-keyword">def</span> <span class="hljs-title function_">create_post</span>(<span class="hljs-params">self, user_id, content</span>):
    <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.posts:
        self.posts[user_id] = []
    post_id = <span class="hljs-built_in">len</span>(self.posts[user_id]) + <span class="hljs-number">1</span>
    timestamp = datetime.now()
    post = {
        <span class="hljs-string">"post_id"</span>: post_id,
        <span class="hljs-string">"user_id"</span>: user_id,
        <span class="hljs-string">"content"</span>: content,
        <span class="hljs-string">"timestamp"</span>: timestamp
    }
    self.posts[user_id].append(post)
    <span class="hljs-keyword">return</span> post_id

<span class="hljs-keyword">def</span> <span class="hljs-title function_">like_post</span>(<span class="hljs-params">self, user_id, post_id</span>):
    <span class="hljs-keyword">if</span> post_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.likes:
        self.likes[post_id] = []
    self.likes[post_id].append(user_id)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_timeline</span>(<span class="hljs-params">self, user_id</span>):
    timeline = []
    <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> self.users.values():
        <span class="hljs-keyword">if</span> user_id != user[<span class="hljs-string">"user_id"</span>]:
            <span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> self.posts.get(user[<span class="hljs-string">"user_id"</span>], []):
                timeline.append(post)
    timeline.sort(key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-string">"timestamp"</span>], reverse=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> timeline

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_comment</span>(<span class="hljs-params">self, user_id, post_id, text</span>):
    <span class="hljs-keyword">if</span> post_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.comments:
        self.comments[post_id] = []
    comment_id = <span class="hljs-built_in">len</span>(self.comments[post_id]) + <span class="hljs-number">1</span>
    timestamp = datetime.now()
    comment = {
        <span class="hljs-string">"comment_id"</span>: comment_id,
        <span class="hljs-string">"post_id"</span>: post_id,
        <span class="hljs-string">"user_id"</span>: user_id,
        <span class="hljs-string">"text"</span>: text,
        <span class="hljs-string">"timestamp"</span>: timestamp
    }
    self.comments[post_id].append(comment)
    <span class="hljs-keyword">return</span> comment_id

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_comments</span>(<span class="hljs-params">self, post_id</span>):
    <span class="hljs-keyword">return</span> self.comments.get(post_id, [])

<span class="hljs-comment"># Example usage:</span> timeline = FacebookTimeline()

<span class="hljs-comment"># Create users</span> timeline.add_user(<span class="hljs-number">1</span>, <span class="hljs-string">"user1"</span>, <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password1"</span>) timeline.add_user(<span class="hljs-number">2</span>, <span class="hljs-string">"user2"</span>, <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password2"</span>) timeline.add_user(<span class="hljs-number">3</span>, <span class="hljs-string">"user3"</span>, <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password3"</span>)

<span class="hljs-comment"># User1 creates a post</span> post_id1 = timeline.create_post(<span class="hljs-number">1</span>, <span class="hljs-string">"This is post 1 by user1"</span>)

<span class="hljs-comment"># User2 likes the post</span> timeline.like_post(<span class="hljs-number">2</span>, post_id1)

<span class="hljs-comment"># User2 adds a comment</span> timeline.add_comment(<span class="hljs-number">2</span>, post_id1, <span class="hljs-string">"This is a comment by user2 on post 1"</span>)

<span class="hljs-comment"># User3 adds a comment</span> timeline.add_comment(<span class="hljs-number">3</span>, post_id1, <span class="hljs-string">"This is a comment by user3 on post 1"</span>)

<span class="hljs-comment"># Get User1's timeline</span> user1_timeline = timeline.get_timeline(<span class="hljs-number">1</span>) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"User1's Timeline:"</span>) <span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> user1_timeline: <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Post <span class="hljs-subst">{post[<span class="hljs-string">'post_id'</span>]}</span>: <span class="hljs-subst">{post[<span class="hljs-string">'content'</span>]}</span> (<span class="hljs-subst">{post[<span class="hljs-string">'timestamp'</span>]}</span>)"</span>) comments = timeline.get_comments(post[<span class="hljs-string">'post_id'</span>]) <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> comments: <span class="hljs-built_in">print</span>(<span class="hljs-string">f" Comment <span class="hljs-subst">{comment[<span class="hljs-string">'comment_id'</span>]}</span>: <span class="hljs-subst">{comment[<span class="hljs-string">'text'</span>]}</span> (<span class="hljs-subst">{comment[<span class="hljs-string">'timestamp'</span>]}</span>)"</span>)</pre></div><h1 id="8278">API Design</h1><ol><li><code>POST /api/user/register</code>: Register a new user.</li><li><code>POST /api/user/login</code>: Authenticate user login.</li><li><code>GET /api/user/{userID}/timeline</code>: Retrieve a user's timeline.</li><li><code>POST /api/user/{userID}/post</code>: Add a new post to the user's timeline.</li><li><code>PUT /api/user/{userID}/post/{postID}</code>: Update an existing post.</li><li><code>DELETE /api/user/{userID}/post/{postID}</code>: Delete a post from the timeline.</li></ol><h1 id="7c1f">User Service API:</h1><h1 id="075e">1. POST /api/user/register:</h1><h2 id="0efe">Request:</h2><div id="b718"><pre>{ <span class="hljs-string">"name"</span>: <span class="hljs-string">"John Doe"</span>, <span class="hljs-string">"email"</span>: <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"strong_password"</span> }</pre></div><h2 id="4a70">Response (Success):</h2><div id="75ed"><pre>{ <span class="hljs-string">"userID"</span>: <span class="hljs-string">"user123"</span>, <span class="hljs-string">"name"</span>: <span class="hljs-string">"John Doe"</span>, <span class="hljs-string">"email"</span>: <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"token"</span>: <span class="hljs-string">"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... (JWT token)"</span> }</pre></div><h2 id="e00f">Response (Error):</h2><div id="6ea6"><pre><span class="hljs-punctuation">{</span> <span class="hljs-attr">"error"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"User with this email already exists."</span> <span class="hljs-punctuation">}</span></pre></div><h1 id="abc6">2. POST /api/user/login:</h1><h2 id="e3df">Request:</h2><div id="8841"><pre>{ <span class="hljs-string">"email"</span>: <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"strong_password"</span> }</pre></div><h2 id="92ac">Response (Success):</h2><div id="af00"><pre>{ <span class="hljs-string">"userID"</span>: <span class="hljs-string">"user123"</span>, <span class="hljs-string">"name"</span>: <span class="hljs-string">"John Doe"</span>, <span class="hljs-string">"email"</span>: <span class="hljs-string">"[email protected]"</span>, <span class="hljs-string">"token"</span>: <span class="hljs-string">"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... (JWT token)"</span> }</pre></div><h2 id="40f0">Response (Error):</h2><div id="c39c"><pre><span class="hljs-punctuation">{</span> <span class="hljs-attr">"error"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Invalid credentials. Please try again."</span> <span class="hljs-punctuation">}</span></pre></div><h1 id="6a27">Timeline Service API:</h1><h1 id="1cbc">1. GET /api/user/{userID}/timeline:</h1><h2 id="6f9c">Response (Success):</h2><div id="d5cf"><pre><span class="hljs-punctuation">{</span> <span class="hljs-attr">"userID"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"user123"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"John Doe"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"timeline"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"postID"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"post1"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"content"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Had a great day at the beach!"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"postDate"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2023-07-20T12:30:00"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"mediaType"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"photo"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"mediaURL"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://example.com/image123.jpg"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"postID"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"post2"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"content"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Excited about the new project."</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"postDate"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2023-07-19T14:45:00"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"mediaType"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"text"</span> <span class="hljs-punctuation">}</span> <span class="hljs-punctuation">]</span> <span class="hljs-punctuation">}</span></pre></div><h1 id="24a0">2. POST /api/user/{userID}/post:</h1><h2 id="ca9e">Request:</h2><div id="1d2c"><pre>{ "<span class="hljs-attribute">content</span>": <span class="hljs-string">"Enjoying a delicious meal."</span>, <span class="hljs-string">"mediaType"</span>: <span class="hljs-string">"photo"</span>, <span class="hljs-string">"mediaURL"</span>: <span class="hljs-string">"https://example.com/image456.jpg"</span> }</pre></div><h2 id="3c64">Response (Success):</h2><div id="9726"><pre><span class="hljs-punctuation">{</span> <span class="hljs-attr">"postID"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"post3"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"content"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Enjoying a delicious meal."</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"postDate"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2023-07-21T09:15:00"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"mediaType"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"photo"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"mediaURL"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://example.com/image456.jpg"</span> <span class="hljs-punctuation">}</span></pre></div><h1 id="3fb1">3. PUT /api/user/{userID}/post/{postID}:</h1><h2 id="63a5">Request:</h2><div id="35ab"><pre>{ "<span class="hljs-attribute">content</span>": <span class="hljs-string">"Enjoying a delicious meal with friends."</span>, <span class="hljs-string">"mediaType"</span>: <span class="hljs-string">"photo"</span>, <span class="hljs-string">"mediaURL"</span>: <span class="hljs-string">"https://example.com/image456.jpg"</span> }</pre></div><h2 id="d8c7">Response (Success):</h2><div id="803d"><pre><span class="hljs-punctuation">{</span> <span class="hljs-attr">"postID"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"post3"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"content"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Enjoying a delicious meal with friends."</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"postDate"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2023-07-21T09:15:00"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"mediaType"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"photo"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"mediaURL"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://example.com/image456.jpg"</span> <span class="hljs-punctuation">}</span></pre></div><h2 id="9f8b">Response (Error):</h2><div id="4d53"><pre><span class="hljs-punctuation">{</span> <span class="hljs-attr">"error"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"You are not authorized to edit this post."</span> <span class="hljs-punctuation">}</span></pre></div><h1 id="84da">4. DELETE /api/user/{userID}/post/{postID}:</h1><h2 id="4e23">Response (Success):</h2><div id="110f"><pre><span class="hljs-punctuation">{</span> <span class="hljs-attr">"message"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Post with ID post3 has been deleted."</span> <span class="hljs-punctuation">}</span></pre></div><h2 id="5335">Response (Error):</h2><div id="9607"><pre><span class="hljs-punctuation">{</span> <span class="hljs-attr">"error"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"You are not authorized to delete this post."</span> <span class="hljs-punctuation">}</span></pre></div><h1 id="0f69">User Service API:</h1><div id="dc13"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, request, jsonify</pre></div><div id="7340"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name)</pre></div><div id="9dda"><pre><span class="hljs-attribute">users</span> <span class="hljs-operator">=</span> {}</pre></div><div id="4987"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/api/user/register'</span>, methods=[<span class="hljs-string">'POST'</span>]) <span class="hljs-keyword">def</span> <span class="hljs-title function_">register_user</span>(): data = request.json email = data[<span class="hljs-string">'email'</span>] <span class="hljs-keyword">if</span> email <span class="hljs-keyword">in</span> <span class="hljs-symbol">users:</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"error"</span>: <span class="hljs-string">"User with this email already exists."</span>}), <span class="hljs-number">400</span>

<span class="hljs-comment"># ... Code to register user and generate token ...</span>

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"userID"</span>: user_id, <span class="hljs-string">"name"</span>: data[<span class="hljs-string">'name'</span>], <span class="hljs-string">"email"</span>: email, <span class="hljs-string">"token"</span>: token}), <span class="hljs-number">201</span></pre></div><div id="8de0"><pre>@app.route(<span class="hljs-string">'/api/user/login'</span>, methods=[<span class="hljs-string">'POST'</span>])

def login_user(): data = request.json email = data[<span class="hljs-string">'email'</span>] if email not in users or users[email][<span class="hljs-string">'password'</span>] != data[<span class="hljs-string">'password'</span>]: return jsonify({<span class="hljs-string">"error"</span>: <span class="hljs-string">"Invalid credentials. Please try again."</span>}), <span class="hljs-number">401</span>

# ... <span class="hljs-symbol">Code</span> to generate token ...

return jsonify({<span class="hljs-string">"userID"</span>: users[email][<span class="hljs-string">'userID'</span>], <span class="hljs-string">"name"</span>: users[email][<span class="hljs-string">'name'</span>], <span class="hljs-string">"email"</span>: email, <span class="hljs-string">"token"</span>: token}), <span class="hljs-number">200</span></pre></div><div id="7597"><pre><span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
app.<span class="hljs-built_in">run</span>(<span class="hljs-attribute">debug</span>=<span class="hljs-literal">True</span>)</pre></div><h1 id="87a8">Timeline Service API:</h1><div id="d4ad"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, request, jsonify</pre></div><div id="e4eb"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(__name__)</pre></div><div id="264d"><pre>timeline_data = {
<span class="hljs-comment">"user123"</span>: {
    <span class="hljs-comment">"name"</span>: <span class="hljs-comment">"John Doe"</span>,
    <span class="hljs-comment">"timeline"</span>: [
        {
            <span class="hljs-comment">"postID"</span>: <span class="hljs-comment">"post1"</span>,
            <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"Had a great day at the beach!"</span>,
            <span class="hljs-comment">"postDate"</span>: <span class="hljs-comment">"2023-07-20T12:30:00"</span>,
            <span class="hljs-comment">"mediaType"</span>: <span class="hljs-comment">"photo"</span>,
            <span class="hljs-comment">"mediaURL"</span>: <span class="hljs-comment">"https://example.com/image123.jpg"</span>
        },
        {
            <span class="hljs-comment">"postID"</span>: <span class="hljs-comment">"post2"</span>,
            <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"Excited about the new project."</span>,
            <span class="hljs-comment">"postDate"</span>: <span class="hljs-comment">"2023-07-19T14:45:00"</span>,
            <span class="hljs-comment">"mediaType"</span>: <span class="hljs-comment">"text"</span>
        }
    ]
}

}</pre></div><div id="68af"><pre><span class="hljs-variable">@app</span>.<span class="hljs-built_in">route</span>(<span class="hljs-string">'/api/user/<string:user_id>/timeline'</span>, methods=[<span class="hljs-string">'GET'</span>]) def <span class="hljs-built_in">get_user_timeline</span>(user_id): if user_id <span class="hljs-keyword">not</span> in <span class="hljs-attribute">timeline_data</span>: return <span class="hljs-built_in">jsonify</span>({<span class="hljs-string">"error"</span>: <span class="hljs-string">"User not found."</span>}), <span class="hljs-number">404</span> return <span class="hljs-built_in">jsonify</span>(timeline_data[user_id]), <span class="hljs-number">200</span></pre></div><div id="1d7b"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/user/<string:user_id>/post'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_post_to_timeline</span>(<span class="hljs-params">user_id</span>): data = request.json <span class="hljs-comment"># ... Code to validate and add the post to the timeline ...</span> post = { <span class="hljs-string">"postID"</span>: <span class="hljs-string">"post3"</span>, <span class="hljs-string">"content"</span>: data[<span class="hljs-string">'content'</span>], <span class="hljs-string">"postDate"</span>: <span class="hljs-string">"2023-07-21T09:15:00"</span>, <span class="hljs-string">"mediaType"</span>: data[<span class="hljs-string">'mediaType'</span>], <span class="hljs-string">"mediaURL"</span>: data[<span class="hljs-string">'mediaURL'</span>] } timeline_data[user_id][<span class="hljs-string">'timeline'</span>].append(post) <span class="hljs-keyword">return</span> jsonify(post), <span class="hljs-number">201</span></pre></div><div id="67c2"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/api/user/<string:user_id>/post/<string:post_id>'</span>, methods=[<span class="hljs-string">'PUT'</span>, <span class="hljs-string">'DELETE'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">edit_or_delete_post</span>(<span class="hljs-params">user_id, post_id</span>): <span class="hljs-comment"># ... Code to edit or delete the post ...</span> <span class="hljs-keyword">if</span> request.method == <span class="hljs-string">'PUT'</span>: <span class="hljs-comment"># ... Code to update the post ...</span> <span class="hljs-keyword">return</span> jsonify(updated_post), <span class="hljs-number">200</span> <span class="hljs-keyword">elif</span> request.method == <span class="hljs-string">'DELETE'</span>: <span class="hljs-comment"># ... Code to delete the post ...</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"message"</span>: <span class="hljs-string">f"Post with ID <span class="hljs-subst">{post_id}</span> has been deleted."</span>}), <span class="hljs-number">200</span></pre></div><div id="7987"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.<span class="hljs-built_in">run</span>(<span class="hljs-attribute">debug</span>=<span class="hljs-literal">True</span>)</pre></div><h1 id="60f5">Complete Detailed Design</h1><p id="a7d1"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="ee78"><i>Subscribe to youtube channel :</i></p><div id="4a6d" class="link-block"> <a href="https://www.youtube.com/@ignito5917/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div> </div> </div> </a> </div><h1 id="5fdb">Complete Code implementation</h1><div id="e6c2"><pre><span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-keyword">class</span> <span class="hljs-title class_">FacebookTimeline</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.posts = []

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_post</span>(<span class="hljs-params">self, content, media_type=<span class="hljs-literal">None</span>, media_url=<span class="hljs-literal">None</span></span>):
    post = {
        <span class="hljs-string">"content"</span>: content,
        <span class="hljs-string">"media_type"</span>: media_type,
        <span class="hljs-string">"media_url"</span>: media_url,
        <span class="hljs-string">"timestamp"</span>: datetime.now()
    }
    self.posts.append(post)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_timeline</span>(<span class="hljs-params">self</span>):
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">sorted</span>(self.posts, key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-string">"timestamp"</span>], reverse=<span class="hljs-literal">True</span>)

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_life_event</span>(<span class="hljs-params">self, event</span>):
    self.posts.append({
        <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Life Event: <span class="hljs-subst">{event}</span>"</span>,
        <span class="hljs-string">"timestamp"</span>: datetime.now()
    })

<span class="hljs-keyword">def</span> <span class="hljs-title function_">set_privacy</span>(<span class="hljs-params">self, post_index, privacy</span>):
    <span class="hljs-keyword">if</span> <span class="hljs-number">0</span> &lt;= post_index &lt; <span class="hljs-built_in">len</span>(self.posts):
        self.posts[post_index][<span class="hljs-string">"privacy"</span>] = privacy

<span class="hljs-keyword">def</span> <span class="hljs-title function_">view_activity_log</span>(<span class="hljs-params">self</span>):
    <span class="hljs-keyword">return</span> self.posts

<span class="hljs-keyword">def</span> <span class="hljs-title function_">feature_post</span>(<span class="hljs-params">self, post_index</span>):
    <span class="hljs-keyword">if</span> <span class="hljs-number">0</span> &lt;= post_index &lt; <span class="hljs-built_in">len</span>(self.posts):
        self.posts.insert(<span class="hljs-number">0</span>, self.posts.pop(post_index))

<span class="hljs-comment"># Example usage:</span> timeline = FacebookTimeline()

timeline.add_post(<span class="hljs-string">"Had a great day at the beach!"</span>, <span class="hljs-string">"photo"</span>, <span class="hljs-string">"https://example.com/beach.jpg"</span>) timeline.add_post(<span class="hljs-string">"Excited about the new project."</span>, <span class="hljs-string">"text"</span>)

timeline.add_life_event(<span class="hljs-string">"Birthday"</span>) timeline.add_life_event(<span class="hljs-string">"Graduation"</span>)

timeline.set_privacy(<span class="hljs-number">0</span>, <span class="hljs-string">"Friends"</span>) timeline.set_privacy(<span class="hljs-number">1</span>, <span class="hljs-string">"Public"</span>)

<span class="hljs-built_in">print</span>(<span class="hljs-string">"Timeline:"</span>) <span class="hljs-built_in">print</span>(timeline.get_timeline())

<span class="hljs-built_in">print</span>(<span class="hljs-string">"\nActivity Log:"</span>) <span class="hljs-built_in">print</span>(timeline.view_activity_log())

timeline.feature_post(<span class="hljs-number">2</span>)

<span class="hljs-built_in">print</span>(<span class="hljs-string">"\nFeatured Timeline:"</span>) <span class="hljs-built_in">print</span>(timeline.get_timeline())</pre></div><h1 id="bd03">System Design — Online Poker Game</h1><p id="786e">We will be discussing in depth -</p><ul><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>What is Online Poker Game</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Important Features</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Scaling Requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Data Model — ER requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>High Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Basic Low Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>API Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Complete Detailed Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Code implementation</b></a></li></ul><figure id="f05d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*jnzYRWcQYQbppWXt.jpg"><figcaption>Pic credits : Pinterest</figcaption></figure><h1 id="a1e4">What is Online Poker Game</h1><p id="019c">Online Poker Game is a popular virtual version of the classic card game, Poker, that allows players from around the world to enjoy the excitement and thrill of poker online. The game enables multiple players to participate in real-time, providing an engaging and interactive platform for poker enthusiasts to showcase their skills and compete with others.</p><h1 id="7070">Important Features</h1><ol><li>User Authentication and Registration: A secure user authentication system with options for registration and login is essential to ensure that players can create accounts and access the platform securely.</li><li>Lobby and Game Selection: A user-friendly lobby interface is crucial for players to view available poker tables, choose stakes, game types, and find opponents to play against.</li><li>Real-Time Gameplay: Online Poker Game should facilitate real-time gameplay with minimal latency to ensure an immersive and seamless gaming experience.</li><li>Gameplay Options: The game should offer various poker variations like Texas Hold’em, Omaha, Seven-card stud, etc., to cater to a wide range of players’ preferences.</li><li>In-Game Chat: Including an in-game chat feature allows players to interact, enhancing the social aspect of the game.</li><li>Game History and Statistics: Keeping track of game history and providing player statistics helps in engaging users and improving their overall experience.</li><li>Secure Transactions: Implementing a secure payment gateway for depositing and withdrawing money is crucial for real-money poker games.</li><li>Anti-Cheating Measures: Integrating measures to detect and prevent cheating is essential to maintain a fair gaming environment.</li></ol><h1 id="82a7">Scaling Requirements — Capacity Estimation</h1><p id="2bf3">For the sake of simplicity, let’s consider a small scale simulation for an Online Poker Game.</p><p id="7087">Assumptions:</p><ul><li><i>Total number of users: 10,000</i></li><li><i>Daily active users (DAU): 2,000</i></li><li><i>Number of poker games played by user/day: 5</i></li><li><i>Total number of poker games played per day: 10,000 games/day</i></li><li><i>Read to write ratio: 100:1</i></li></ul><p id="7b68">Storage Estimation:</p><ul><li>Let’s assume each poker game generates approximately 100 KB of data.</li><li>Total Storage per day: 10,000 games/day * 100 KB = 1 GB/day</li><li>For the next 3 years: 1 GB/day * 365 * 3 = 1.095 TB</li></ul><p id="17e2">Requests per Second:</p><ul><li>Requests per second = 10,000 games/day / (24 hours * 3600 seconds) = ~0.12 requests/second</li></ul><div id="d4d5"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify

app = Flask(name)

<span class="hljs-comment"># Data structures to simulate game data</span> games = {}

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/create_game'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_game</span>(): data = request.get_json() game_id = data.get(<span class="hljs-string">'game_id'</span>) <span class="hljs-comment"># Check if the game_id already exists</span> <span class="hljs-keyword">if</span> game_id <span class="hljs-keyword">in</span> games: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game ID already exists'</span>}), <span class="hljs-number">400</span>

<span class="hljs-comment"># Store the game data</span>
games[game_id] = data
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game created successfully'</span>}), <span class="hljs-number">201</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/get_game/<int:game_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_game</span>(<span class="hljs-params">game_id</span>): <span class="hljs-comment"># Check if the game_id exists</span> <span class="hljs-keyword">if</span> game_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> games: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game not found'</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Return the game data</span>
<span class="hljs-keyword">return</span> jsonify(games[game_id]), <span class="hljs-number">200</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/play_game/<int:game_id>'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">play_game</span>(<span class="hljs-params">game_id</span>): <span class="hljs-comment"># Check if the game_id exists</span> <span class="hljs-keyword">if</span> game_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> games: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game not found'</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Simulate game play logic</span>
data = games[game_id]
player_id = request.get_json().get(<span class="hljs-string">'player_id'</span>)
action = request.get_json().get(<span class="hljs-string">'action'</span>)
<span class="hljs-comment"># Perform the player action on the game data (e.g., bet, fold, etc.)</span>

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">f'Player <span class="hljs-subst">{player_id}</span> performed action: <span class="hljs-subst">{action}</span>'</span>}), <span class="hljs-number">200</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()</pre></div><h1 id="c27a">Data Model — ER requirements</h1><ol><li>User: Stores user information such as username, email, password, and account balance.</li><li>Game: Represents individual poker games with attributes like game type, stakes, start time, and end time.</li><li>Table: Each table hosts one game and has attributes like table ID, maximum number of players, and current players seated.</li><li>Player: Represents a player’s association with a specific table, including attributes like player ID, seat number, and status (active, folded, etc.).</li><li>Cards: Stores information about each card in the deck, including its value and suit.</li><li>Chat: Manages in-game chat messages with attributes like message ID, sender, receiver, and timestamp.</li></ol><div id="76b3"><pre><span class="hljs-operator">+</span><span class="hljs-comment">--------------------+ +--------------------+</span> <span class="hljs-operator">|</span> Users <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> Games <span class="hljs-operator">|</span> <span class="hljs-operator">+</span><span class="hljs-comment">--------------------+ +--------------------+</span> <span class="hljs-operator">|</span> UserId (<span class="hljs-keyword">Primary</span> Key)<span class="hljs-operator">|</span><span class="hljs-comment">----------<| GameId (Primary Key)|</span> <span class="hljs-operator">|</span> Username <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> GameName <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> Email <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> GameType <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> Password <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> Stakes <span class="hljs-operator">|</span> <span class="hljs-operator">+</span><span class="hljs-comment">--------------------+ | CreatorUserId (FK) |</span> <span class="hljs-operator">+</span><span class="hljs-comment">--------------------+</span> <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> v <span class="hljs-operator">+</span><span class="hljs-comment">-------------------+</span> <span class="hljs-operator">|</span> UserGames <span class="hljs-operator">|</span> <span class="hljs-operator">+</span><span class="hljs-comment">-------------------+</span> <span class="hljs-operator">|</span> UserGameId (PK) <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> UserId (FK) <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> GameId (FK) <span class="hljs-operator">|</span> <span class="hljs-operator">|</span> JoinedAt <span class="hljs-operator">|</span> <span class="hljs-operator">+</span><span class="hljs-comment">-------------------+</span></pre></div><h1 id="125a">High Level Design</h1><ol><li>Traffic Handling: The system should be able to handle a large number of concurrent players, table creations, and game updates without significant performance degradation.</li><li>Database Scalability: As the user base grows, the database should be able to handle the increasing load efficiently.</li><li>Load Balancing: Implementing load balancing mechanisms is essential to distribute traffic evenly across multiple servers and prevent bottlenecks.</li><li>Caching Strategy: Caching frequently accessed data can significantly reduce database load and improve response times.</li><li>Frontend: Responsible for the user interface, game representation, and communication with backend services.</li><li>Backend Application: Manages game logic, user authentication, and game state management.</li><li>Game Engine: Implements the rules of poker and ensures fair gameplay.</li><li>Database: Stores user data, game information, and chat messages.</li></ol><p id="fe77"><b>Assumptions:</b></p><ul><li>The system is read-heavy, with more users viewing ongoing games than creating new games.</li><li>The system needs to be highly available and reliable.</li><li>The system should be able to handle real-time updates and interactions during gameplay.</li><li>Players will have the option to follow and interact with each other during the game.</li></ul><p id="bd14"><b>Main Components and Services for Online Poker Game:</b></p><ol><li>Mobile Client: Users will access the Online Poker Game through mobile applications or web browsers.</li><li>Application Servers: These servers will handle the business logic, including game management, user authentication, and real-time interactions.</li><li>Load Balancer: To distribute incoming requests to different application servers for load balancing.</li><li>Cache (Memcache): Used to store frequently accessed data and improve response time.</li><li>CDN: Content Delivery Network to optimize and deliver static assets like images and media.</li><li>Database: NoSQL databases for storing user and game-related data.</li><li>WebSocket Server: To enable real-time communication and game updates between players during gameplay.</li></ol><p id="3772"><b>Services</b>:</p><ol><li>Authentication Service: Responsible for user registration, login, and token-based authentication.</li><li>Game Management Service: Handles the creation, management, and deletion of poker games.</li><li>User Interaction Service: Manages user interactions, such as following other players and sending/receiving game invites.</li><li>Gameplay Service: Implements the rules and logic for different poker game variations.</li><li>Real-Time Communication Service: Enables real-time communication between players during gameplay.</li><li>Feed Generation Service: Generates and updates user-specific feeds based on the games they follow and their interactions.</li><li>Payment Service: Integrates with a secure payment gateway to handle real-money transactions for players.</li><li>Anti-Cheating Service: Implements algorithms and mechanisms to detect and prevent cheating during gameplay.</li><li>Analytics Service: Collects and analyzes user activity data to gain insights into player behavior and game performance.</li><li>Notification Service: Sends real-time notifications to players about game invites, updates, and other relevant events.</li><li>Image/Video Processing Service: Handles image and video processing, including image resizing and thumbnail generation.</li><li>Storage Service: Stores images, videos, and other media assets in a scalable and reliable storage system.</li></ol><p id="9877">Authentication Service:</p><ul><li>Functionality: User registration, login, and token-based authentication.</li></ul><div id="55b4"><pre><span class="hljs-comment"># authentication_service.py</span> <span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify <span class="hljs-keyword">import</span> bcrypt <span class="hljs-keyword">import</span> jwt <span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime, timedelta</pre></div><div id="bdd9"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name)</pre></div><div id="7a05"><pre><span class="hljs-comment"># Dummy database for user storage</span> <span class="hljs-attr">users</span> = {} <span class="hljs-comment"># {username: {'password': hashed_password, 'user_id': user_id}}</span></pre></div><div id="b391"><pre><span class="hljs-comment"># Secret key for JWT</span> <span class="hljs-attr">SECRET_KEY</span> = <span class="hljs-string">'your_secret_key'</span> </pre></div><div id="af8a"><pre><span class="hljs-meta">@app</span>.route(<span class="hljs-string">'/register'</span>, methods=[<span class="hljs-string">'POST'</span>]) def register(): <span class="hljs-keyword">data</span> = request.get_json() username = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'username'</span>) password = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'password'</span>) <span class="hljs-keyword">if</span> not username or not password: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Username and password are required'</span>}), <span class="hljs-number">400</span></pre></div><div id="6c79"><pre> <span class="hljs-keyword">if</span> username <span class="hljs-keyword">in</span> <span class="hljs-built_in">users</span>: <span class="hljs-built_in">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Username already exists'</span>}), 400</pre></div><div id="1488"><pre> hashed_password = bcrypt<span class="hljs-selector-class">.hashpw</span>(password<span class="hljs-selector-class">.encode</span>(<span class="hljs-string">'utf-8'</span>), bcrypt<span class="hljs-selector-class">.gensalt</span>()) user_id = <span class="hljs-built_in">len</span>(users) + <span class="hljs-number">1</span> users<span class="hljs-selector-attr">[username]</span> = {<span class="hljs-string">'password'</span>: hashed_password, <span class="hljs-string">'user_id'</span>: user_id} return <span class="hljs-built_in">jsonify</span>({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Registration successful'</span>}), <span class="hljs-number">201</span> </pre></div><div id="0010"><pre><span class="hljs-variable">@app</span>.<span class="hljs-built_in">route</span>(<span class="hljs-string">'/login'</span>, methods=[<span class="hljs-string">'POST'</span>]) def <span class="hljs-built_in">login</span>(): data = request.<span class="hljs-built_in">get_json</span>() username = data.<span class="hljs-built_in">get</span>(<span class="hljs-string">'username'</span>) password = data.<span class="hljs-built_in">get</span>(<span class="hljs-string">'password'</span>) if <span class="hljs-keyword">not</span> username or <span class="hljs-keyword">not</span> password or username <span class="hljs-keyword">not</span> in users or <span class="hljs-keyword">not</span> bcrypt.<span class="hljs-built_in">checkpw</span>(password.<span class="hljs-built_in">encode</span>(<span class="hljs-string">'utf-8'</span>), users[username][<span class="hljs-string">'password'</span>]): return <span class="hljs-built_in">jsonify</span>({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Invalid credentials'</span>}), <span class="hljs-number">401</span></pre></div><div id="92c6"><pre> <span class="hljs-comment"># Generate and return JWT token upon successful login</span> token = jwt.encode({<span class="hljs-string">'user_id'</span>: <span class="hljs-built_in">users</span>[username][<span class="hljs-string">'user_id'</span>], <span class="hljs-string">'exp'</span>: datetime.utcnow() + timedelta(days=1)}, SECRET_KEY, algorithm=<span class="hljs-string">'HS256'</span>) <span class="hljs-built_in">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Login successful'</span>, <span class="hljs-string">'token'</span>: token}), 200 </pre></div><div id="fd5a"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.<span class="hljs-built_in">run</span>()</pre></div><p id="d7a2">Game Management Service:</p><ul><li>Functionality: Creation, management, and deletion of poker games.</li></ul><div id="1f54"><pre><span class="hljs-comment"># game_management_service.py</span> <span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify <span class="hljs-keyword">import</span> uuid</pre></div><div id="9497"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name)</pre></div><div id="d051"><pre># Dummy <span class="hljs-keyword">database</span> <span class="hljs-keyword">for</span> game <span class="hljs-keyword">storage</span> games = {} # {game_id: {<span class="hljs-string">'game_name'</span>: <span class="hljs-type">name</span>, <span class="hljs-string">'game_type'</span>: <span class="hljs-keyword">type</span>, <span class="hljs-string">'stakes'</span>: stakes, <span class="hljs-string">'creator_user_id'</span>: creator_user_id}} </pre></div><div id="eef0"><pre><span class="hljs-meta">@app</span>.route(<span class="hljs-string">'/create_game'</span>, methods=[<span class="hljs-string">'POST'</span>]) def create_game(): <span class="hljs-keyword">data</span> = request.get_json() game_name = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'game_name'</span>) game_type = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'game_type'</span>) stakes = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'stakes'</span>) creator_user_id = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'creator_user_id'</span>)</pre></div><div id="8f7f"><pre> <span class="hljs-variable language_">game_id</span> = str(uuid.uuid4()) games[<span class="hljs-variable language_">game_id</span>] = {<span class="hljs-string">'game_name'</span>: game_name, <span class="hljs-string">'game_type'</span>: game_type, <span class="hljs-string">'stakes'</span>: stakes, <span class="hljs-string">'creator_user_id'</span>: creator_user_id} <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game created successfully'</span>, <span class="hljs-string">'game_id'</span>: <span class="hljs-variable language_">game_id</span>}), <span class="hljs-number">201</span> </pre></div><div id="235f"><pre><span class="hljs-variable">@app</span>.<span class="hljs-built_in">route</span>(<span class="hljs-string">'/get_game/<game_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]) def <span class="hljs-built_in">get_game</span>(game_id): if game_id <span class="hljs-keyword">not</span> in <span class="hljs-attribute">games</span>: return <span class="hljs-built_in">jsonify</span>({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game not found'</span>}), <span class="hljs-number">404</span></pre></div><div id="1d2d"><pre> <span class="hljs-keyword">return</span> jsonify(games[<span class="hljs-variable language_">game_id</span>]), <span class="hljs-number">200</span> </pre></div><div id="7f49"><pre><span class="hljs-variable">@app</span>.<span class="hljs-built_in">route</span>(<span class="hljs-string">'/delete_game/<game_id>'</span>, methods=[<span class="hljs-string">'DELETE'</span>]) def <span class="hljs-built_in">delete_game</span>(game_id): if game_id <span class="hljs-keyword">not</span> in <span class="hljs-attribute">games</span>: return <span class="hljs-built_in">jsonify</span>({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game not found'</span>}), <span class="hljs-number">404</span></pre></div><div id="4c0d"><pre> <span class="hljs-selector-tag">del</span> games<span class="hljs-selector-attr">[game_id]</span> return <span class="hljs-built_in">jsonify</span>({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game deleted successfully'</span>}), <span class="hljs-number">200</span> </pre></div><div id="d33d"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.<span class="hljs-built_in">run</span>()</pre></div><h1 id="f65b">Basic Low Level Design</h1><div id="09c7"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify

app = Flask(name)

users = {} <span class="hljs-comment"># Dictionary to store registered users</span> tables = {} <span class="hljs-comment"># Dictionary to store created poker tables</span> messages = [] <span class="hljs-comment"># List to store chat messages</span>

<span class="hljs-comment"># User Authentication API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/register'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">register</span>(): data = request.get_json() username = data.get(<span class="hljs-string">'username'</span>) password = data.get(<span class="hljs-string">'password'</span>) <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> username <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> password: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Username and password are required'</span>}), <span class="hljs-number">400</span>

<span class="hljs-keyword">if</span> username <span class="hljs-keyword">in</span> users:
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Username already exists'</span>}), <span class="hljs-number">400</span>

users[username] = {<span class="hljs-string">'password'</span>: password}
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Registration successful'</span>}), <span class="hljs-number">201</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/login'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">login</span>(): data = request.get_json() username = data.get(<span class="hljs-string">'username'</span>) password = data.get(<span class="hljs-string">'password'</span>) <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> username <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> password <span class="hljs-keyword">or</span> username <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> users <span class="hljs-keyword">or</span> users[username][<span class="hljs-string">'password'</span>] != password: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Invalid credentials'</span>}), <span class="hljs-number">401</span>

<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Login successful'</span>, <span class="hljs-string">'token'</span>: <span class="hljs-string">'your_generated_token'</span>}), <span class="hljs-number">200</span>

<span class="hljs-comment"># Game Management API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/create_table'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_table</span>(): data = request.get_json() <span class="hljs-comment"># Extract table parameters like game type, stakes, etc.</span> <span class="hljs-comment"># Validate the data and create a new table entry in tables dictionary</span> table_id = <span class="hljs-string">'your_generated_table_id'</span> tables[table_id] = {<span class="hljs-string">'params'</span>: data} <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Table created'</span>, <span class="hljs-string">'table_id'</span>: table_id}), <span class="hljs-number">201</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/join_table'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">join_table</span>(): data = request.get_json() table_id = data.get(<span class="hljs-string">'table_id'</span>) <span class="hljs-keyword">if</span> table_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> tables: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Table not found'</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Handle player joining the table</span>
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Joined table successfully'</span>}), <span class="hljs-number">200</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/start_game'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">start_game</span>(): data = request.get_json() table_id = data.get(<span class="hljs-string">'table_id'</span>) <span class="hljs-keyword">if</span> table_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> tables: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Table not found'</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># Check if the table has enough players and start the game</span>
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game started'</span>}), <span class="hljs-number">200</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/end_game'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">end_game</span>(): data = request.get_json() table_id = data.get(<span class="hljs-string">'table_id'</span>) <span class="hljs-keyword">if</span> table_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> tables: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Table not found'</span>}), <span class="hljs-number">404</span>

<span class="hljs-comment"># End the game and calculate winners</span>
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Game ended'</span>}), <span class="hljs-number">200</span>

<span class="hljs-comment"># Gameplay API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/bet'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">bet</span>(): data = request.get_json() <span class="hljs-comment"># Validate data and handle betting logic</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Bet placed'</span>}), <span class="hljs-number">200</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/fold'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">fold</span>(): data = request.get_json() <span class="hljs-comment"># Validate data and handle folding logic</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Folded'</span>}), <span class="hljs-number">200</span>

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/show_cards'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">show_cards</span>(): data = request.get_json() <span class="hljs-comment"># Validate data and handle showing cards logic</span> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Cards shown'</span>}), <span class="hljs-number">200</span>

<span class="hljs-comment"># Chat API</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/send_message'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">send_message</span>(): data = request.get_json() sender = data.get(<span class="hljs-string">'sender'</span>) receiver = data.get(<span class="hljs-string">'receiver'</span>) message = data.get(<span class="hljs-string">'message'</span>) <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> sender <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> receiver <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> message: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Sender, receiver, and message are required'</span>}), <span class="hljs-number">400</span>

<span class="hljs-comment"># Add the message to the messages list or save it in the database</span>
messages.append({<span class="hljs-string">'sender'</span>: sender, <span class="hljs-string">'receiver'</span>: receiver, <span class="hljs-string">'message'</span>: message})
<span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Message sent'</span>}), <span class="hljs-number">200</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()</pre></div><h1 id="6001">API Design</h1><ol><li>User Authentication API: Endpoints for user registration and login.</li><li>Game Management API: Facilitates creating and joining tables, starting games, and ending games.</li><li>Gameplay API: Allows players to perform actions like betting, folding, and showing cards during gameplay.</li><li>Chat API: Handles in-game chat messages between players.</li></ol><div id="5195"><pre><span class="hljs-selector-tag">User</span> <span class="hljs-selector-tag">Authentication</span> <span class="hljs-selector-tag">API</span>: <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">register</span>: <span class="hljs-selector-tag">Allows</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">user</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">register</span> <span class="hljs-selector-tag">with</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">system</span>. <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">login</span>: <span class="hljs-selector-tag">Allows</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">registered</span> <span class="hljs-selector-tag">user</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">log</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">and</span> <span class="hljs-selector-tag">receive</span> <span class="hljs-selector-tag">an</span> <span class="hljs-selector-tag">authentication</span> <span class="hljs-selector-tag">token</span>.

<span class="hljs-selector-tag">Game</span> <span class="hljs-selector-tag">Management</span> <span class="hljs-selector-tag">API</span>: <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">create_table</span>: <span class="hljs-selector-tag">Creates</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">new</span> <span class="hljs-selector-tag">poker</span> <span class="hljs-selector-tag">table</span> <span class="hljs-selector-tag">with</span> <span class="hljs-selector-tag">specified</span> <span class="hljs-selector-tag">parameters</span> <span class="hljs-selector-tag">like</span> <span class="hljs-selector-tag">game</span> <span class="hljs-selector-tag">type</span> <span class="hljs-selector-tag">and</span> <span class="hljs-selector-tag">stakes</span>. <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">join_table</span>: <span class="hljs-selector-tag">Allows</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">user</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">join</span> <span class="hljs-selector-tag">an</span> <span class="hljs-selector-tag">existing</span> <span class="hljs-selector-tag">poker</span> <span class="hljs-selector-tag">table</span> <span class="hljs-selector-tag">with</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">given</span> <span class="hljs-selector-tag">table</span> <span class="hljs-selector-tag">ID</span>. <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">start_game</span>: <span class="hljs-selector-tag">Starts</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">game</span> <span class="hljs-selector-tag">on</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">table</span> <span class="hljs-selector-tag">with</span> <span class="hljs-selector-tag">sufficient</span> <span class="hljs-selector-tag">players</span>. <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">end_game</span>: <span class="hljs-selector-tag">Ends</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">game</span> <span class="hljs-selector-tag">and</span> <span class="hljs-selector-tag">calculates</span> <span class="hljs-selector-tag">winners</span> <span class="hljs-selector-tag">on</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">table</span>.

<span class="hljs-selector-tag">Gameplay</span> <span class="hljs-selector-tag">API</span>: <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">bet</span>: <span class="hljs-selector-tag">Allows</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">player</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">place</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">bet</span> <span class="hljs-selector-tag">during</span> <span class="hljs-selector-tag">their</span> <span class="hljs-selector-tag">turn</span>. <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">fold</span>: <span class="hljs-selector-tag">Allows</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">player</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">fold</span> <span class="hljs-selector-tag">their</span> <span class="hljs-selector-tag">hand</span> <span class="hljs-selector-tag">during</span> <span class="hljs-selector-tag">their</span> <span class="hljs-selector-tag">turn</span>. <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">show_cards</span>: <span class="hljs-selector-tag">Allows</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">player</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">reveal</span> <span class="hljs-selector-tag">their</span> <span class="hljs-selector-tag">cards</span> <span class="hljs-selector-tag">after</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">game</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">over</span>.

<span class="hljs-selector-tag">Chat</span> <span class="hljs-selector-tag">API</span>: <span class="hljs-selector-tag">POST</span> /<span class="hljs-selector-tag">send_message</span>: <span class="hljs-selector-tag">Allows</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">user</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">send</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">chat</span> <span class="hljs-selector-tag">message</span> <span class="hljs-selector-tag">during</span> <span class="hljs-selector-tag">gameplay</span>.</pre></div><h1 id="880f">Complete Detailed Design</h1><p id="a56f"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="278a"><i>Subscribe to youtube channel :</i></p><div id="7077" class="link-block"> <a href="https://www.youtube.com/@ignito5917/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div> </div> </div> </a> </div><h1 id="1018">Complete Code implementation</h1><p id="13de">User Authentication and Registration:</p><div id="ce3f"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, request, jsonify <span class="hljs-keyword">import</span> bcrypt</pre></div><div id="326e"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name)</pre></div><div id="9301"><pre><span class="hljs-attr">users</span> = {} <span class="hljs-comment"># Dictionary to store registered users</span> </pre></div><div id="2186"><pre><span class="hljs-meta">@app</span>.route(<span class="hljs-string">'/register'</span>, methods=[<span class="hljs-string">'POST'</span>]) def register(): <span class="hljs-keyword">data</span> = request.get_json() username = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'username'</span>) password = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'password'</span>) <span class="hljs-keyword">if</span> not username or not password: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Username and password are required'</span>}), <span class="hljs-number">400</span></pre></div><div id="c804"><pre> <span class="hljs-keyword">if</span> username <span class="hljs-keyword">in</span> <span class="hljs-built_in">users</span>: <span class="hljs-built_in">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Username already exists'</span>}), 400</pre></div><div id="79bd"><pre> hashed_password = bcrypt<span class="hljs-selector-class">.hashpw</span>(password<span class="hljs-selector-class">.encode</span>(<span class="hljs-string">'utf-8'</span>), bcrypt<span class="hljs-selector-class">.gensalt</span>()) users<span class="hljs-selector-attr">[username]</span> = {<span class="hljs-string">'password'</span>: hashed_password} return <span class="hljs-built_in">jsonify</span>({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Registration successful'</span>}), <span class="hljs-number">201</span> </pre></div><div id="b50d"><pre><span class="hljs-variable">@app</span>.<span class="hljs-built_in">route</span>(<span class="hljs-string">'/login'</span>, methods=[<span class="hljs-string">'POST'</span>]) def <span class="hljs-built_in">login</span>(): data = request.<span class="hljs-built_in">get_json</span>() username = data.<span class="hljs-built_in">get</span>(<span class="hljs-string">'username'</span>) password = data.<span class="hljs-built_in">get</span>(<span class="hljs-string">'password'</span>) if <span class="hljs-keyword">not</span> username or <span class="hljs-keyword">not</span> password or username <span class="hljs-keyword">not</span> in users or <span class="hljs-keyword">not</span> bcrypt.<span class="hljs-built_in">checkpw</span>(password.<span class="hljs-built_in">encode</span>(<span class="hljs-string">'utf-8'</span>), users[username][<span class="hljs-string">'password'</span>]): return <span class="hljs-built_in">jsonify</span>({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Invalid credentials'</span>}), <span class="hljs-number">401</span></pre></div><div id="5276"><pre> <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Login successful'</span>, <span class="hljs-string">'token'</span>: <span class="hljs-string">'your_generated_token'</span>}), <span class="hljs-number">200</span> </pre></div><div id="5efc"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.<span class="hljs-built_in">run</span>()</pre></div><p id="d6ec">Lobby and Game Selection:</p><div id="0f38"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, jsonify</pre></div><div id="b969"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name)</pre></div><div id="8abe"><pre># Placeholder data <span class="hljs-keyword">for</span> available poker <span class="hljs-keyword">tables</span> poker_tables = [ {<span class="hljs-string">'id'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'game_type'</span>: <span class="hljs-string">'Texas Hold'</span>em<span class="hljs-string">', '</span>stakes<span class="hljs-string">': '</span>Low<span class="hljs-string">', '</span>players<span class="hljs-string">': 3}, {'</span>id<span class="hljs-string">': 2, '</span>game_typ<span class="hljs-string">e': '</span>Omaha<span class="hljs-string">', '</span>stakes<span class="hljs-string">': '</span>High<span class="hljs-string">', '</span>players<span class="hljs-string">': 2}, {'</span>id<span class="hljs-string">': 3, '</span>game_typ<span class="hljs-string">e': '</span>Seven-card Stud<span class="hljs-string">', '</span>stakes<span class="hljs-string">': '</span>Medium<span class="hljs-string">', '</span>players<span class="hljs-string">': 4}, ] </span></pre></div><div id="9262"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/get_tables'</span>, methods=[<span class="hljs-string">'GET'</span>]) <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_tables</span>(): <span class="hljs-keyword">return</span> jsonify(poker_tables), <span class="hljs-number">200</span> </pre></div><div id="f327"><pre><span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/join_table/<int:table_id>'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">join_table</span>(<span class="hljs-params">table_id</span>): table = <span class="hljs-built_in">next</span>((t <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> poker_tables <span class="hljs-keyword">if</span> t[<span class="hljs-string">'id'</span>] == table_id), <span class="hljs-literal">None</span>) <span class="hljs-keyword">if</span> table <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>: <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Table not found'</span>}), <span class="hljs-number">404</span></pre></div><div id="a26a"><pre> <span class="hljs-comment"># Handle player joining the table</span> <span class="hljs-built_in">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Joined table successfully'</span>}), 200 </pre></div><div id="b049"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.<span class="hljs-built_in">run</span>()</pre></div><p id="fb0e">Real-Time Gameplay and In-Game Chat:</p><p id="4886">For real-time gameplay and chat, you can extend the WebSocket implementation using Flask-SocketIO. The following example demonstrates the server-side code:</p><div id="27a5"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> <span class="hljs-title class_">Flask</span>, render_template <span class="hljs-keyword">from</span> flask_socketio <span class="hljs-keyword">import</span> <span class="hljs-title class_">SocketIO</span>, emit</pre></div><div id="c56a"><pre><span class="hljs-attribute">app</span> <span class="hljs-operator">=</span> Flask(name) <span class="hljs-attribute">socketio</span> <span class="hljs-operator">=</span> SocketIO(app)</pre></div><div id="bd71"><pre><span class="hljs-comment"># Dictionary to store active game rooms</span> <span class="hljs-attr">active_game_rooms</span> = {} </pre></div><div id="557d"><pre><span class="hljs-variable">@app</span>.route(<span class="hljs-string">'/'</span>) <span class="hljs-keyword">def</span> <span class="hljs-title function_">index</span>(): <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'index.html'</span>) </pre></div><div id="5cdd"><pre><span class="hljs-variable">@socketio</span>.on(<span class="hljs-string">'connect'</span>) <span class="hljs-keyword">def</span> <span class="hljs-title function_">handle_connect</span>(): <span class="hljs-comment"># Handle new player connection</span> emit(<span class="hljs-string">'message'</span>, {<span class="hljs-string">'data'</span>: <span class="hljs-string">'Connected successfully'</span>}) </pre></div><div id="05e1"><pre><span class="hljs-meta">@socketio.on(<span class="hljs-params"><span class="hljs-string">'disconnect'</span></span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">handle_disconnect</span>(): <span class="hljs-comment"># Handle player disconnection</span> <span class="hljs-keyword">pass</span> </pre></div><div id="cbe9"><pre><span class="hljs-meta">@socketio.on(<span class="hljs-params"><span class="hljs-string">'join_game'</span></span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">handle_join_game</span>(<span class="hljs-params">data</span>): game_room_id = data.get(<span class="hljs-string">'game_room_id'</span>) <span class="hljs-keyword">if</span> game_room_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> active_game_rooms: <span class="hljs-comment"># Handle error if the game room does not exist</span> <span class="hljs-keyword">pass</span></pre></div><div id="6850"><pre> <span class="hljs-comment"># Handle player joining the game room</span> join_room(game_room_id) emit(<span class="hljs-string">'message'</span>, {<span class="hljs-string">'data'</span>: <span class="hljs-string">'You joined the game'</span>}, room=request.sid) </pre></div><div id="8d5d"><pre><span class="hljs-meta">@socketio</span>.on(<span class="hljs-string">'chat_message'</span>) def handle_chat_message(<span class="hljs-keyword">data</span>): game_room_id = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'game_room_id'</span>) sender = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'sender'</span>) message = <span class="hljs-keyword">data</span>.<span class="hljs-keyword">get</span>(<span class="hljs-string">'message'</span>) <span class="hljs-keyword">if</span> game_room_id not <span class="hljs-keyword">in</span> active_game_rooms: # Handle error <span class="hljs-keyword">if</span> the game room does not exist pass</pre></div><div id="c64d"><pre> <span class="hljs-comment"># Handle the received chat message and broadcast it to all players in the same game</span> emit(<span class="hljs-string">'chat_message'</span>, {<span class="hljs-string">'sender'</span>: sender, <span class="hljs-string">'message'</span>: message}, room=game_room_id) </pre></div><div id="ef68"><pre><span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: socketio.<span class="hljs-built_in">run</span>(app)</pre></div><h1 id="cfde">System Design — Amazon Locker</h1><p id="15f4">We will be discussing in depth -</p><ul><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>What is Amazon Locker</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Important Features</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Scaling Requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Data Model — ER requirements</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>High Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Basic Low Level Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>API Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Complete Detailed Design</b></a></li><li><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Code implementation</b></a></li></ul><figure id="0db9"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*A4T2PQVd4V_wIJQg"><figcaption>Pic credits : Pinterest</figcaption></figure><h1 id="c5c8">What is Amazon Locker</h1><p id="3c4e">Amazon Locker is a convenient and secure self-service delivery and pick-up solution provided by Amazon. It aims to address the challenges of delivering packages to customers who may not have a fixed delivery address or prefer not to have packages delivered to their homes or workplaces.</p><h1 id="0feb">Important Features</h1><ol><li>Secure Storage: Amazon Lockers are equipped with robust security measures, including secure access codes and video surveillance, ensuring the safety of packages.</li><li>Contactless Pickup and Drop-off: Users can easily pick up and drop off packages without any human interaction, making it a convenient and efficient solution.</li><li>Multiple Locker Sizes: Lockers come in various sizes to accommodate packages of different dimensions, enhancing flexibility for customers and delivery personnel.</li><li>24/7 Accessibility: Amazon Lockers are accessible 24/7, allowing customers to pick up their packages at their convenience.</li></ol><h1 id="4bd6">Scaling Requirements — Capacity Estimation</h1><p id="16ea">Smalll scale simulation of Amazon locker, let’s say —</p><p id="10ea"><i>Total number of users: 1.2 Billion</i></p><ul><li><i>Daily active users (DAU): 300 Million</i></li><li><i>Number of packages picked up by user/day: 3</i></li><li><i>Total number of packages picked up per day: 900 Million packages/day</i></li><li><i>Read to write ratio: 100:1 (read-heavy system)</i></li><li><i>Total number of packages delivered/day = 1/100 * 900 Million = 9 Million/day</i></li></ul><p id="7636">Storage Estimation:</p><ul><li>Let’s assume, on average, each package’s size is 5 MB.</li><li>Total Storage per day: 9 Million * 5 MB = 45 TB/day</li><li>For the next 3 years, 45 TB * 5 * 365 = 82.125 PB (Petabytes)</li></ul><p id="ee82">Requests per Second:</p><ul><li>Requests per second = 900 Million / (3600 seconds * 24 hours) ≈ 10,416 requests/second</li></ul><div id="3fe1"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">AmazonLocker</span>: <span class="hljs-keyword">def</span> <span class="hljs-title function_">init</span>(<span class="hljs-params">self</span>): self.locker_locations = {} <span class="hljs-comment"># Simulating locker locations</span> self.packages = {} <span class="hljs-comment"># Simulating package data</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_locker_location</span>(<span class="hljs-params">self, location_id, location_name, total_lockers</span>):
    <span class="hljs-comment"># Simulating adding a locker location with specified number of lockers</span>
    self.locker_locations[location_id] = {<span class="hljs-string">'name'</span>: location_name, <span class="hljs-string">'total_lockers'</span>: total_lockers}

<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_package</span>(<span class="hljs-params">self, package_id, package_size, locker_location</span>):
    <span class="hljs-comment"># Simulating adding a package to a locker location</span>
    <span class="hljs-keyword">if</span> locker_location <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.locker_locations:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Locker location not found."</span>
    
    <span class="hljs-keyword">if</span> package_id <span class="hljs-keyword">in</span> self.packages:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Package ID already exists."</span>
    
    self.packages[package_id] = {<span class="hljs-string">'size'</span>: package_size, <span class="hljs-string">'location'</span>: locker_location}
    self.locker_locations[locker_location][<span class="hljs-string">'total_lockers'</span>] -= <span class="hljs-number">1</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">pickup_package</span>(<span class="hljs-params">self, package_id</span>):
    <span class="hljs-comment"># Simulating the process of picking up a package</span>
    <span class="hljs-keyword">if</span> package_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.packages:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Package not found."</span>
    
    locker_location = self.packages[package_id][<span class="hljs-string">'location'</span>]
    self.locker_locations[locker_location][<span class="hljs-string">'total_lockers'</span>] += <span class="hljs-number">1</span>
    <span class="hljs-keyword">del</span> self.packages[package_id]
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Package picked up successfully."</span>

<span class="hljs-comment"># Creating an instance of AmazonLocker</span> amazon_locker = AmazonLocker()

<span class="hljs-comment"># Adding a locker location with 1000 lockers</span> amazon_locker.add_locker_location(<span class="hljs-number">1</span>, <span class="hljs-string">"Main Street Locker"</span>, <span class="hljs-number">1000</span>)

<span class="hljs-comment"># Adding a package to the locker location with package_id and size 5 MB</span> amazon_locker.add_package(<span class="hljs-string">"PKG123"</span>, <span class="hljs-number">5</span>, <span class="hljs-number">1</span>)

<span class="hljs-comment"># Picking up the package with package_id "PKG123"</span> result = amazon_locker.pickup_package(<span class="hljs-string">"PKG123"</span>) <span class="hljs-built_in">print</span>(result) <span class="hljs-comment"># Output: Package picked up successfully.</span></pre></div><h1 id="e5c5">Data Model — ER requirements</h1><ol><li>Locker: Represents an individual locker unit with a unique identifier and its current status (e.g., available, occupied).</li><li>User: Stores user information, including unique user IDs, delivery preferences, and historical usage.</li><li>Package: Represents a package with attributes such as size, delivery status, and recipient details.</li><li>Location: Stores information about each locker location, including its address and available locker capacities.</li></ol><div id="6a82"><pre>User

<span class="hljs-symbol">user_id:</span> int (Primary <span class="hljs-keyword">Key</span>) <span class="hljs-symbol">username:</span> <span class="hljs-type">string</span> <span class="hljs-symbol">email:</span> <span class="hljs-type">string</span> <span class="hljs-symbol">password:</span> <span class="hljs-type">string</span>

LockerLocation

<span class="hljs-symbol">location_id:</span> int (Primary <span class="hljs-keyword">Key</span>) <span class="hljs-symbol">location_name:</span> <span class="hljs-type">string</span> <span class="hljs-symbol">total_lockers:</span> int

Locker

<span class="hljs-symbol">locker_id:</span> int (Primary <span class="hljs-keyword">Key</span>) <span class="hljs-symbol">location_id:</span> int (Foreign <span class="hljs-keyword">Key</span> <span class="hljs-keyword">to</span> LockerLocation) <span class="hljs-symbol">occupied:</span> bool

Package

<span class="hljs-symbol">package_id:</span> int (Primary <span class="hljs-keyword">Key</span>) <span class="hljs-symbol">user_id:</span> int (Foreign <span class="hljs-keyword">Key</span> <span class="hljs-keyword">to</span> User) <span class="hljs-symbol">locker_id:</span> int (Foreign <span class="hljs-keyword">Key</span> <span class="hljs-keyword">to</span> Locker) <span class="hljs-symbol">photo_url:</span> <span class="hljs-type">string</span> <span class="hljs-symbol">caption:</span> <span class="hljs-type">string</span> <span class="hljs-symbol">post_timestamp:</span> datetime <span class="hljs-symbol">location:</span> <span class="hljs-type">string</span></pre></div><h1 id="f3c3">High Level Design</h1><ol><li>User Interface: A user-friendly interface that allows customers to select an Amazon Locker location during checkout and receive their pickup codes.</li><li>Locker Management Service: Responsible for tracking locker availability, assigning lockers to packages, and managing package pickup.</li><li>Package Delivery Service: Handles the process of delivering packages from fulfillment centers to the selected Amazon Locker locations.</li><li>Authentication and Security: Ensures secure access to lockers through unique pickup codes and authentication mechanisms.</li><li>Location Expansion: The system should be easily scalable to add new locker locations in various geographic regions.</li><li>Concurrent Users: The design must handle a large number of concurrent users accessing the lockers during peak times.</li><li>Storage Capacity: The system should efficiently manage and allocate locker storage space for different package sizes.</li><li>Redundancy and High Availability: To ensure continuous service, the system should be resilient with redundant components and high availability architecture.</li></ol><p id="d4c5"><b>Assumptions</b>:</p><ul><li>The system is read-heavy with more package pickups (reads) than package uploads (writes).</li><li>High reliability and availability are critical for package pickups and deliveries.</li></ul><p id="b097"><b>Main Components and Services:</b></p><ol><li>Mobile Client: Represents the users accessing the Amazon Locker platform through a mobile application.</li><li>Application Servers: Handle read, write, and notification operations for the Amazon Locker platform.</li><li>Load Balancer: Routes and directs requests from mobile clients to the appropriate application servers to balance the load.</li><li>Cache (Memcache): Caches frequently accessed data to improve response times for read-heavy operations.</li><li>CDN (Content Delivery Network): Improves the latency and throughput for delivering package-related data to users.</li><li>Database (NoSQL): Stores data related to users, lockers, packages, follows, likes, and comments.</li><li>Storage (HDFS or Amazon S3): Stores and manages the actual package photos and related metadata.</li></ol><p id="34a4"><b>Main Services for Amazon Locker System:</b></p><ol><li>Package Service: Handles operations related to packages, such as uploading new packages, associating packages with lockers, and retrieving package information.</li><li>User Service: Manages user-related operations, including user registration, authentication, and fetching user information.</li><li>Locker Service: Manages the state of lockers, including marking them as occupied or available.</li></ol><h1 id="5db4">Basic Low Level Design</h1><div id="2d1c"><pre><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify <span class="hljs-keyword">import</span> datetime

app = Flask(name)

<span class="hljs-comment"># Sample data to be stored in the server</span> users = {} locker_locations = {} lockers = {} packages = {} follows = {} likes = {} comments = {}

<span class="hljs-comment"># Endpoint for creating a new user</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_user</span>(): data = request.json user_id = <span class="hljs-built_in">len</span>(users) + <span class="hljs-number">1</span> user = User(user_id, data[<span class="hljs-string">'username'</span>], data[<span class="hljs-string">'email'</span>], data[<span class="hljs-string">'password'</span>]) users[user_id] = user <span class="hljs-keyword">return</span> jsonify(user.dict), <span class="hljs-number">201</span>

<span class="hljs-comment"># Endpoint for retrieving user information</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/users/<int:user_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user</span>(<span class="hljs-params">user_id</span>): user = users.get(user_id) <span class="hljs-keyword">if</span> user: <span class="hljs-keyword">return</span> jsonify(user.dict), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"User not found"</span>, <span class="hljs-number">404</span>

<span class="hljs-comment"># Endpoint for adding a new locker location</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/locker_locations'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_locker_location</span>(): data = request.json location_id = <span class="hljs-built_in">len</span>(locker_locations) + <span class="hljs-number">1</span> location = LockerLocation(location_id, data[<span class="hljs-string">'location_name'</span>], data[<span class="hljs-string">'total_lockers'</span>]) locker_locations[location_id] = location <span class="hljs-keyword">return</span> jsonify(location.dict), <span class="hljs-number">201</span>

<span class="hljs-comment"># Endpoint for adding a new locker</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/lockers'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_locker</span>(): data = request.json locker_id = <span class="hljs-built_in">len</span>(lockers) + <span class="hljs-number">1</span> locker = Locker(locker_id, data[<span class="hljs-string">'location_id'</span>]) lockers[locker_id] = locker <span class="hljs-keyword">return</span> jsonify(locker.dict), <span class="hljs-number">201</span>

<span class="hljs-comment"># Endpoint for creating a new package</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/packages'</span>, methods=[<span class="hljs-string">'POST'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_package</span>(): data = request.json package_id = <span class="hljs-built_in">len</span>(packages) + <span class="hljs-number">1</span> user_id = data[<span class="hljs-string">'user_id'</span>] locker_id = data[<span class="hljs-string">'locker_id'</span>] photo_url = data[<span class="hljs-string">'photo_url'</span>] caption = data[<span class="hljs-string">'caption'</span>] post_timestamp = datetime.datetime.now() location = data[<span class="hljs-string">'location'</span>] package = Package(package_id, user_id, locker_id, photo_url, caption, post_timestamp, location) packages[package_id] = package <span class="hljs-keyword">return</span> jsonify(package.dict), <span class="hljs-number">201</span>

<span class="hljs-comment"># Endpoint for retrieving package information</span> <span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/packages/<int:package_id>'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_package</span>(<span class="hljs-params">package_id</span>): package = packages.get(package_id) <span class="hljs-keyword">if</span> package: <span class="hljs-keyword">return</span> jsonify(package.dict), <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"Package not found"</span>, <span class="hljs-number">404</span>

<span class="hljs-keyword">if</span> name == <span class="hljs-string">'main'</span>: app.run()</pre></div><h1 id="f960">API Design</h1><div id="8d15"><pre>User API

<span class="hljs-title function_ invoke__">select_locker_location</span>(user_id: <span class="hljs-type">str</span>, location_id: <span class="hljs-type">str</span>) <span class="hljs-punctuation">-></span> <span class="hljs-type">str</span>: Allows users to select an Amazon Locker location during checkout and returns a unique pickup code. <span class="hljs-title function_ invoke__">get_user_orders</span>(user_id: <span class="hljs-type">str</span>) <span class="hljs-punctuation">-></span> List[Dict[<span class="hljs-type">str</span>, Any]]: Retrieves a list of the user<span class="hljs-symbol">'s</span> past orders and their delivery status.

Locker API

<span class="hljs-title function_ invoke__">get_available_lockers</span>(location_id: <span class="hljs-type">str</span>) <span class="hljs-punctuation">-></span> List[<span class="hljs-type">str</span>]: Returns a list of available locker IDs at a specific location. <span class="hljs-title function_ invoke__">assign_locker</span>(package_id: <span class="hljs-type">str</span>, locker_id: <span class="hljs-type">str</span>) <span class="hljs-punctuation">-></span> <span class="hljs-type">bool</span>: Assigns a package to a specific locker.

Package API

<span class="hljs-title function_ invoke__">create_package</span>(package_details: Dict[<span class="hljs-type">str</span>, Any]) <span class="hljs-punctuation">-></span> <span class="hljs-type">str</span>: Creates a new package with the provided details and returns the package ID. <span class="hljs-title function_ invoke__">get_package_details</span>(package_id: <span class="hljs-type">str</span>) <span class="hljs-punctuation">-></span> Dict[<span class="hljs-type">str</span>, Any]: Retrieves the details of a specific package. <span class="hljs-title function_ invoke__">update_package_status</span>(package_id: <span class="hljs-type">str</span>, status: <span class="hljs-type">str</span>) <span class="hljs-punctuation">-></span> <span class="hljs-type">bool</span>: Updates the delivery status of a package.</pre></div><div id="8a4c"><pre><span class="hljs-comment"># Data structures to simulate the database</span> users = {} lockers = {} packages = {}

<span class="hljs-comment"># User API</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">select_locker_location</span>(<span class="hljs-params"><span class="hljs-symbol">user_id:</span> str, <span class="hljs-symbol">location_id:</span> str</span>) -> <span class="hljs-symbol">str:</span> <span class="hljs-comment"># Check if the user exists in the database</span> <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> <span class="hljs-symbol">users:</span> <span class="hljs-keyword">return</span> <span class="hljs-string">"User not found."</span>

<span class="hljs-comment"># Fetch available lockers at the specified location</span>
available_lockers = get_available_lockers(location_id)

<span class="hljs-comment"># Choose a locker randomly for simplicity (in a real system, a more sophisticated logic would be used)</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-symbol">available_lockers:</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"No lockers available at the selected location."</span>

selected_locker = available_lockers[<span class="hljs-number">0</span>]

<span class="hljs-comment"># Assign the locker to the user's package</span>
assign_locker(user_id, selected_locker)

<span class="hljs-keyword">return</span> f<span class="hljs-string">"Your pickup code for Locker {selected_locker} is: {users[user_id]['pickup_code']}"</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_user_orders</span>(<span class="hljs-params"><span class="hljs-symbol">user_id:</span> str</span>) -> <span class="hljs-title class_">List</span>[<span class="hljs-title class_">Dict</span>[str, <span class="hljs-title class_">Any</span>]]: <span class="hljs-comment"># Check if the user exists in the database</span> <span class="hljs-keyword">if</span> user_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> <span class="hljs-symbol">users:</span> <span class="hljs-keyword">return</span> []

<span class="hljs-comment"># In a real system, retrieve the user's orders and their delivery status from the database</span>
<span class="hljs-keyword">return</span> users[user_id].get(<span class="hljs-string">'orders'</span>, [])

<span class="hljs-comment"># Locker API</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_available_lockers</span>(<span class="hljs-params"><span class="hljs-symbol">location_id:</span> str</span>) -> <span class="hljs-title class_">List</span>[str]: <span class="hljs-comment"># In a real system, fetch available lockers at the specified location from the database</span> <span class="hljs-comment"># For this example, we assume all lockers are available</span> <span class="hljs-keyword">return</span> [locker_id <span class="hljs-keyword">for</span> locker_id, locker <span class="hljs-keyword">in</span> lockers.items() <span class="hljs-keyword">if</span> locker[<span class="hljs-string">'location'</span>] == location_id <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> locker[<span class="hljs-string">'occupied'</span>]]

<span class="hljs-keyword">def</span> <span class="hljs-title function_">assign_locker</span>(<span class="hljs-params"><span class="hljs-symbol">user_id:</span> str, <span class="hljs-symbol">locker_id:</span> str</span>) -> <span class="hljs-symbol">bool:</span> <span class="hljs-comment"># Check if the locker exists in the database</span> <span class="hljs-keyword">if</span> locker_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> <span class="hljs-symbol">lockers:</span> <span class="hljs-keyword">return</span> <span class="hljs-title class_">False</span>

<span class="hljs-comment"># Check if the locker is available</span>
<span class="hljs-keyword">if</span> lockers[locker_id][<span class="hljs-string">'occupied'</span>]:
    <span class="hljs-keyword">return</span> <span class="hljs-title class_">False</span>

<span class="hljs-comment"># Assign the locker to the user's package</span>
users[user_id][<span class="hljs-string">'assigned_locker'</span>] = locker_id

<span class="hljs-comment"># Update the locker status to occupied</span>
lockers[locker_id][<span class="hljs-string">'occupied'</span>] = <span class="hljs-title class_">True</span>

<span class="hljs-keyword">return</span> <span class="hljs-title class_">True</span>

<span class="hljs-comment"># Package API</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_package</span>(<span class="hljs-params"><span class="hljs-symbol">package_details:</span> <span class="hljs-title class_">Dict</span>[str, <span class="hljs-title class_">Any</span>]</span>) -> <span class="hljs-symbol">str:</span> <span class="hljs-comment"># Generate a unique package ID (in a real system, this would be done differently)</span> package_id = f<span class="hljs-string">"PKG-{len(packages) + 1}"</span>

<span class="hljs-comment"># Add the package to the database</span>
packages[package_id] = package_details

<span class="hljs-keyword">return</span> package_id

<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_package_details</span>(<span class="hljs-params"><span class="hljs-symbol">package_id:</span> str</span>) -> <span class="hljs-title class_">Dict</span>[str, <span class="hljs-title class_">Any</span>]: <span class="hljs-comment"># Check if the package exists in the database</span> <span class="hljs-keyword">if</span> package_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> <span class="hljs-symbol">packages:</span> <span class="hljs-keyword">return</span> {}

<span class="hljs-keyword">return</span> packages[package_id]

<span class="hljs-keyword">def</span> <span class="hljs-title function_">update_package_status</span>(<span class="hljs-params"><span class="hljs-symbol">package_id:</span> str, <span class="hljs-symbol">status:</span> str</span>) -> <span class="hljs-symbol">bool:</span> <span class="hljs-comment"># Check if the package exists in the database</span> <span class="hljs-keyword">if</span> package_id <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> <span class="hljs-symbol">packages:</span> <span class="hljs-keyword">return</span> <span class="hljs-title class_">False</span>

<span class="hljs-comment"># Update the package status</span>
packages[package_id][<span class="hljs-string">'status'</span>] = status
<span class="hljs-keyword">return</span> <span class="hljs-title class_">True</span></pre></div><h1 id="9b4f">Complete Detailed Design</h1><p id="f6ac"><i>Coming soon! It will be covered on youtube channel.</i></p><p id="41a3"><i>Subscribe to youtube channel :</i></p><div id="7f64" class="link-block">
      <a href="https://www.youtube.com/@ignito5917/about">
        <div>
          <div>
            <h2>Ignito</h2>
            <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div>
            <div><p>www.youtube.com</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*wHu6OdmQemSe6DWJ)"></div>
          </div>
        </div>
      </a>
    </div><h1 id="03e1">Complete Code implementation</h1><p id="3232">Secure Storage:</p><div id="cfe3"><pre><span class="hljs-comment"># Function to simulate the secure storage feature</span>

def <span class="hljs-title function_ invoke__">secure_storage</span>(<span class="hljs-attr">package_id</span>: str, <span class="hljs-attr">access_code</span>: str) -> <span class="hljs-keyword">bool</span>: <span class="hljs-comment"># Simulate the process of locking the locker and associating the access code with the package</span> <span class="hljs-keyword">if</span> package_id in packages <span class="hljs-keyword">and</span> not packages[package_id][<span class="hljs-string">'locked'</span>]: packages[package_id][<span class="hljs-string">'access_code'</span>] = access_code packages[package_id][<span class="hljs-string">'locked'</span>] = True <span class="hljs-keyword">return</span> True <span class="hljs-keyword">return</span> False</pre></div><p id="2fd5">Contactless Pickup and Drop-off:</p><div id="b007"><pre><span class="hljs-comment"># Function to simulate contactless pickup and drop-off</span> def <span class="hljs-title function_ invoke__">contactless_pickup_dropoff</span>(<span class="hljs-attr">package_id</span>: str) -> <span class="hljs-keyword">bool</span>: <span class="hljs-comment"># Simulate the process of unlocking the locker and removing the package</span> <span class="hljs-keyword">if</span> package_id in packages <span class="hljs-keyword">and</span> packages[package_id][<span class="hljs-string">'locked'</span>]: packages[package_id][<span class="hljs-string">'locked'</span>] = False <span class="hljs-keyword">return</span> True <span class="hljs-keyword">return</span> False</pre></div><p id="5d6f">Multiple Locker Sizes:</p><div id="0aaf"><pre><span class="hljs-comment"># Function to add a new locker with a specified size</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_locker</span>(<span class="hljs-params">locker_id: <span class="hljs-built_in">str</span>, size: <span class="hljs-built_in">str</span></span>): lockers[locker_id] = {<span class="hljs-string">'size'</span>: size, <span class="hljs-string">'occupied'</span>: <span class="hljs-literal">False</span>}</pre></div><p id="c4a9">Mobile Integration:</p><div id="4181"><pre><span class="hljs-comment"># Function to generate a unique pickup code and associate it with a package</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">generate_pickup_code</span>(<span class="hljs-params"><span class="hljs-symbol">package_id:</span> str</span>) -> <span class="hljs-symbol">str:</span> <span class="hljs-comment"># Simulate the process of generating a unique pickup code for the package</span> pickup_code = f<span class="hljs-string">"CODE-{package_id[-3:]}"</span> packages[package_id][<span class="hljs-string">'pickup_code'</span>] = pickup_code <span class="hljs-keyword">return</span> pickup_code</pre></div><h1 id="c96c">Read next — how to Design the Dropbox.</h1><div id="93df" class="link-block"> <a href="https://readmedium.com/day-9-of-system-design-case-studies-series-design-dropbox-ead523ccccfa"> <div> <div> <h2>Day 9 of System Design Case Studies Series : Design Dropbox</h2> <div><h3>Complete Design with examples</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*4HuovOqLBjgPIO3GMPDh2Q.png)"></div> </div> </div> </a> </div><p id="404a"><b><i>Let me know if you have any questions in the comment section below. Subscribe/ Follow, Like/Clap and Stay Tuned!!</i></b></p><blockquote id="08a3"><p><b>Day 1 : <a href="https://readmedium.com/day-1-of-15-days-of-advanced-sql-series-a3676272dd5f?sk=991e8c82a9c378675080b83254ad13a2">SQL Basics and Kick start of Advanced SQL Series</a></b></p></blockquote><blockquote id="3423"><p><b>Day 2 : <a href="https://readmedium.com/day-1-of-15-days-of-advanced-sql-series-a3676272dd5f?sk=991e8c82a9c378675080b83254ad13a2">SQL Basics, Query Structure, Built In functions Conditions</a></b></p></blockquote><blockquote id="9f47"><p><b>Day 3 : <a href="https://readmedium.com/day-3-of-15-days-of-advanced-sql-series-c2ab52598a50?sk=bf9fb75360feb5d6506d04d011414d76">Most Important Commands, Joins and Filters</a></b></p></blockquote><blockquote id="b9e1"><p><b>Day 4 : <a href="https://readmedium.com/day-4-of-15-days-of-advanced-sql-series-3c06c9e1fc26?sk=336c132c67279805ba770156ed8e506d">Set Theory Operations, Stored Procedures and CASE statements in SQL</a></b></p></blockquote><blockquote id="718d"><p><b>Day 5 : <a href="https://readmedium.com/day-5-of-15-days-of-advanced-sql-series-310023a4083?sk=81c0eed74a24f3e43e54a0f087b898e7">Wildcards, Aggregation and Sequences in SQL</a></b></p></blockquote><blockquote id="daec"><p><b>Day 6 : <a href="https://readmedium.com/day-6-of-15-days-of-advanced-sql-series-548769f14138?sk=5a1b436c8b6ca2a738ba865f1972ee19">Subqueries, Group by, order by and Having clauses in SQL and Analytical Functions</a></b></p></blockquote><blockquote id="d268"><p><b>Day 7 : <a href="https://readmedium.com/day-7-of-15-days-of-advanced-sql-series-5f93bbfa734?sk=1b0e08bb48cf75d76f327053814ad4a7">Window Functions, Grouping Sets and Constraints in SQL</a></b></p></blockquote><blockquote id="fe1f"><p><b>Day 8 : <a href="https://readmedium.com/day-8-of-15-days-of-advanced-sql-series-8387b74d270?sk=2734fb4be2e7968e0fa27612785a76ed">BigQuery Basics, SELECT, FROM, WHERE and Date and Extract in BigQuery</a></b></p></blockquote><blockquote id="653c"><p><b>Day 9 : <a href="https://readmedium.com/day-9-of-15-days-of-advanced-sql-series-6bfde9f997a6?sk=fa5b407ba124825c5b3b26109999e28b">Common Expression Table, UNNEST Clause, SQL vs NoSQL Databases</a></b></p></blockquote><blockquote id="9d00"><p><b>Day 10 : <a href="https://readmedium.com/day-10-of-15-days-of-advanced-sql-series-9cb7438b1442?sk=437428d85d85281fa9c289fbafbaaa50">Triggers, Pivot and Cursors in SQL</a></b></p></blockquote><blockquote id="badc"><p><b>Day 11 : <a href="https://readmedium.com/day-11-of-15-days-of-advanced-sql-series-fbb863662786?sk=1342587e4be148ab2931280b52a3c05d">Views, Indexes and Auto Increment in SQL</a></b></p></blockquote><blockquote id="3b11"><p><b>Day 12 : <a href="https://readmedium.com/day-12-of-15-days-of-advanced-sql-series-98654987d9aa?sk=4c294f3c9807b87cceb52d6d8d7222bc">Query optimizations, Performance tuning in SQL</a></b></p></blockquote><blockquote id="8826"><p><b>Day 13 : <a href="https://readmedium.com/day-13-of-15-days-of-advanced-sql-series-991a315b73cf?sk=caacd74f6702270130e1875932e96d39">Introduction to MySQL, PostgreSQL and Mongo DB, Comparison between MySQL and PostgreSQL and Mongo DB, Introduction to SQL and NoSQL Databases</a></b></p></blockquote><blockquote id="5e9a"><p><b>Day 14 : <a href="https://readmedium.com/day-14-of-15-days-of-advanced-sql-series-c6126c3e8601?sk=221dc236be193d224b30a9d1972d3bb5">MySQL in Depth</a></b></p></blockquote><blockquote id="06b2"><p><b>Day 15 : <a href="https://readmedium.com/day-15-of-15-days-of-advanced-sql-series-9309f860bf1c?sk=4f44ece49732072fa796334f1611fc27">PostgreSQL inDepth</a></b></p></blockquote><p id="9662">Anyways, For Day 15 of 15 days of Advanced SQL, we will cover —</p><blockquote id="6da9"><p><b>PostgreSQL inDepth</b></p></blockquote><p id="bba6"><b><i>Github for Advanced SQL that you can follow —</i></b></p><div id="325c" class="link-block"> <a href="https://github.com/Coder-World04/Complete-Advanced-SQL-Series/blob/main/README.md"> <div> <div> <h2>Complete-Advanced-SQL-Series/README.md at main · Coder-World04/Complete-Advanced-SQL-Series</h2> <div><h3>This repository contains everything you need to become proficient in Advanced SQL Structured Query Language Query…</h3></div> <div><p>github.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*Ryx7inaYd_Q2GsQu)"></div> </div> </div> </a> </div><p id="3f6b"><b><i>All the projects, data structures, algorithms, system design, Data Science and ML, Data Engineering, MLOps and Deep Learning videos will be published on our youtube channel ( just launched).</i></b></p><p id="f10f"><b><i>Subscribe today!</i></b></p><div id="7232" class="link-block"> <a href="https://www.youtube.com/channel/UCOdLTXh9sIiBR_s9yh3-bEQ/about"> <div> <div> <h2>Ignito</h2> <div><h3>Excited to share that we have launched our Youtube channel — Ignito to cover all the projects and coding exercise for …</h3></div> <div><p>www.youtube.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*okwkD4LOH9YJcx2S)"></div> </div> </div> </a> </div><h1 id="29d1">System Design Case Studies — In Depth</h1><blockquote id="f5c2"><p><a href="https://readmedium.com/day-4-of-system-design-case-studies-series-design-instagram-part-1-10943440f29c?sk=38e68a213058e169e71754e00c501813"><b>Design Instagram</b></a></p></blockquote><blockquote id="4c87"><p><a href="https://readmedium.com/day-5-of-system-design-case-studies-series-design-messenger-app-7b73c589f4a?sk=4a53b122e8f02836c17fa35622aa0309"><b>Design Messenger App</b></a></p></blockquote><blockquote id="ca00"><p><a href="https://readmedium.com/day-7-of-system-design-case-studies-series-design-twitter-fd0722d7bb7c?sk=cdfc23d38edd5f48dc30efdcc0801c3e"><b>Design Twitter</b></a></p></blockquote><blockquote id="52bb"><p><a href="https://readmedium.com/day-8-of-system-design-case-studies-series-design-url-shortener-91c812a08e0b?sk=5e20d426c91ebaacfe43031bc43642da"><b>Design URL Shortener</b></a></p></blockquote><blockquote id="dcc2"><p><a href="https://readmedium.com/day-9-of-system-design-case-studies-series-design-dropbox-ead523ccccfa?sk=03b3b4ea3633051f7a9a7d379b1066b8"><b>Design Dropbox</b></a></p></blockquote><blockquote id="25bf"><p><a href="https://readmedium.com/day-10-of-system-design-case-studies-series-design-youtube-58bc4ad09c4b?sk=18560ffcc3d7174566d38d60c99d4914"><b>Design Youtube</b></a></p></blockquote><blockquote id="6d16"><p><a href="https://readmedium.com/day-11-of-system-design-case-studies-series-design-api-rate-limiter-8627993c5a92?sk=fad32cada40f414aef47b7928dfb7e67"><b>Design API Rate Limiter</b></a></p></blockquote><blockquote id="3942"><p><a href="https://readmedium.com/day-12-of-system-design-case-studies-series-design-web-crawler-efba93f40030?sk=185e88e37fbc3d30dcaf41bc3863a868"><b>Design Web Crawler</b></a></p></blockquote><blockquote id="80bf"><p><a href="https://naina0412.medium.com/day-13-of-system-design-case-studies-series-design-facebooks-newsfeed-e96294c7d871?sk=f0956b536721902c7da6a1ec8e2f0880"><b>Design Facebook’s Newsfeed</b></a></p></blockquote><blockquote id="2353"><p><a href="https://readmedium.com/day-14-of-system-design-case-studies-series-design-yelp-af432d13e838?sk=55e19b7d8ad43c4109e9b1694678c177"><b>Design Yelp</b></a></p></blockquote><blockquote id="dcb7"><p><a href="https://readmedium.com/day-15-of-system-design-case-studies-series-design-uber-2adc612701d?sk=d1c5481fcfd4f30e84074e5a5d7c548e"><b>Design Uber</b></a></p></blockquote><blockquote id="580e"><p><a href="https://readmedium.com/day-16-of-system-design-case-studies-series-design-tinder-a0867163f449?sk=6313f0b9760c3d78a17443a98bdb3330"><b>Design Tinder</b></a></p></blockquote><blockquote id="6b84"><p><a href="https://readmedium.com/day-17-of-system-design-case-studies-series-design-tiktok-58e5a93bcfb5?sk=5eed7cbac7af8b6506951417514ec8e0"><b>Design Tiktok</b></a></p></blockquote><blockquote id="1a51"><p><a href="https://readmedium.com/day-18-of-system-design-case-studies-series-design-whatsapp-38ec39f32b44?sk=89cc7003e78917fd65330ad56a7ed8f0"><b>Design Whatsapp</b></a></p></blockquote><blockquote id="86fc"><p><a href="https://readmedium.com/most-popular-system-design-questions-mega-compilation-45218129fe26?sk=6432dd01c067dd28bc81da1dfceccdab"><b>Most Popular System Design Questions</b></a></p></blockquote><blockquote id="a7f7"><p><a href="https://readmedium.com/quick-roundup-solved-system-design-case-studies-6ad776d437cf?sk=e42f56968e1b592382f484c222e7c111"><b>Mega Compilation : Solved System Design Case studies</b></a></p></blockquote><h1 id="c325">Complete Data Structures and Algorithm Series</h1><blockquote id="c8f1"><p><a href="https://readmedium.com/day-4-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-83d4c90d9115?sk=8ab3d284915f8f28534651d1c9cf41e5"><b>Complexity Analysis</b></a></p></blockquote><blockquote id="c155"><p><a href="https://readmedium.com/day-5-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-backtracking-f7de93dbe72d?sk=08c8ce11404387e46fdd73013aec267f"><b>Backtracking</b></a></p></blockquote><blockquote id="66fd"><p><a href="https://readmedium.com/day-3-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-af62dc4aec9c?sk=704354dbc4c0048ac0a0b5c97f1eef0e"><b>Sliding Window</b></a></p></blockquote><blockquote id="da37"><p><a href="https://readmedium.com/day-6-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-greedy-technique-4b219a8488d0?sk=540b74ce2d13f345dd00cbbfb252815f"><b>Greedy Technique</b></a></p></blockquote><blockquote id="d262"><p><a href="https://readmedium.com/day-8-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-two-pointer-7c513302dfa9?sk=cc32bc3ce22139845c64d195553859e0"><b>Two pointer Technique</b></a></p></blockquote><blockquote id="43b9"><p><a href="https://readmedium.com/day-11-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-arrays-bf7045a3c98b?sk=42ad70a29aa9f7891794d7feaa63bea9"><b>Arrays</b></a></p></blockquote><blockquote id="8dbb"><p><a href="https://readmedium.com/day-13-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-linked-list-6536f0041153?sk=952899c3d2e2bd5b4dbd6c8ad7debf05"><b>Linked List</b></a></p></blockquote><blockquote id="29e2"><p><a href="https://readmedium.com/day-12-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-strings-fa27c45a5fd6?sk=f6b3fc7bf5c770d2d04107667be1c446"><b>Strings</b></a></p></blockquote><blockquote id="95aa"><p><a href="https://readmedium.com/day-14-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-stack-b26d68eb3477?sk=ed28cc4e45134ad3562a3594ddea4017"><b>Stack</b></a></p></blockquote><blockquote id="d072"><p><a href="https://readmedium.com/day-15-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-queue-db38d5477cd5?sk=44ae516bf0f1da510ee9618b7f135995"><b>Queues</b></a></p></blockquote><blockquote id="0e08"><p><a href="https://readmedium.com/day-17-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-hash-ddfe72657211?sk=a457b598d5f5f3d2572029693c587198"><b>Hash Table/Hashing</b></a></p></blockquote><blockquote id="b6d3"><p><a href="https://readmedium.com/day-16-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-binary-search-8799ce6321cb?sk=e4ee1b96f1cd2f9531b5e739539d8b7e"><b>Binary Search</b></a></p></blockquote><blockquote id="5586"><p><a href="https://readmedium.com/day-7-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-1-d-dynamic-2560f585499?sk=0756b6bd798238d9a96fe3d161690350"><b>1- D Dynamic Programming</b></a></p></blockquote><blockquote id="be69"><p><a href="https://readmedium.com/day-10-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-divide-and-a00f7375507?sk=3d52023dade6f37c396b58e039ca29f2"><b>Divide and Conquer Technique</b></a></p></blockquote><blockquote id="b173"><p><a href="https://readmedium.com/day-9-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-recursion-ed6f7f41742?sk=bf98ce6abdb3e3f2fa71213c6ed8caa9"><b>Recursion</b></a></p></blockquote><p id="9215"><b>Github —</b></p><div id="3244" class="link-block"> <a href="https://github.com/Coder-World04/Complete-Data-Structures-and-Algorithms"> <div> <div> <h2>GitHub — Coder-World04/Complete-Data-Structures-and-Algorithms: This repository contains everything…</h2> <div><h3>This repository contains everything you need to become proficient in Data Structures and Algorithms Start here : Day 1…</h3></div> <div><p>github.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*82WWl4vZvYx1zwkR)"></div> </div> </div> </a> </div><h1 id="c583">Some of the other best Series —</h1><blockquote id="ca4e"><p><a href="https://readmedium.com/day-1-day-60-quick-recap-of-60-days-of-data-science-and-ml-6fc021643d1?sk=4e75e043b7630a9f963562ebac94e129"><b>60 days of Data Science and ML Series with projects</b></a></p></blockquote><blockquote id="1ff6"><p><a href="https://readmedium.com/quick-recap-30-days-of-natural-language-processing-nlp-with-projects-series-ceb674e3c09b?sk=ca09b27b3d5867f23ab4dc367b6c0c32"><b>30 Days of Natural Language Processing ( NLP) Series</b></a></p></blockquote><blockquote id="c2cf"><p><a href="https://readmedium.com/day-1-of-30-days-of-machine-learning-ops-7c299e4b09be?sk=4ab48350a5c359fc157109e48b1d738f"><b>30 days of Machine Learning Ops</b></a></p></blockquote><blockquote id="5c01"><p><a href="https://readmedium.com/day-1-of-30-days-of-data-structures-and-algorithms-and-system-design-simplified-dsa-and-system-965e860ec677?sk=aa49bdbc46a72f600cb51774f0aea6b6"><b>30 days of Data Structures and Algorithms and System Design Simplified</b></a></p></blockquote><blockquote id="f2fd"><p><a href="https://readmedium.com/day-1-of-60-days-of-deep-learning-with-projects-series-4a5caa305cf6?sk=89f3d43dd450035546bf3a8cf85bb125"><b>60 Days of Deep Learning with Projects Series</b></a></p></blockquote><blockquote id="b8a0"><p><a href="https://readmedium.com/day-1-of-30-days-of-data-engineering-894822fcb128?sk=76ba558bfe2d9f85cbe741e505295531"><b>30 days of Data Engineering with projects Series</b></a></p></blockquote><blockquote id="9d85"><p><a href="https://readmedium.com/day-1-data-science-and-ml-research-papers-simplified-a68b00a3b1c4?sk=56136229ff738bd734f19d2b6953f78c"><b>Data Science and Machine Learning Research ( papers) Simplified</b></a><b> **</b></p></blockquote><blockquote id="fb06"><p><a href="https://readmedium.com/100-days-your-data-science-and-ml-degree-part-3-c621ecfdf711?sk=1a8c7b0c204d73432d56b7d1a3a26474"><b>100 days : Your Data Science and Machine Learning Degree Series with projects</b></a></p></blockquote><blockquote id="5203"><p><a href="https://ai.plainenglish.io/23-data-science-techniques-you-should-know-61bc2c9d1b3a?sk=1680c36193eb22198974c9008d62a33c"><b>23 Data Science Techniques You Should Know</b></a></p></blockquote><blockquote id="ac12"><p><a href="https://readmedium.com/mega-post-tech-interview-the-only-list-of-questions-you-need-to-practice-ee349ea197bb?sk=fac3614684daff4b50a70c0a71e4d528"><b>Tech Interview Series — Curated List of coding questions</b></a></p></blockquote><blockquote id="dede"><p><a href="https://readmedium.com/system-design-made-easy-quick-recap-of-complete-system-design-34af7e3aedfb?sk=bdd6a19edc1f3ce4a5064923f5b68721"><b>Complete System Design with most popular Questions Series</b></a></p></blockquote><blockquote id="6508"><p><a href="https://readmedium.com/complete-data-preprocessing-and-data-visualization-with-projects-mega-compilation-part-2-41584ef0920e?sk=842390da51689b8d43148c3980570db0"><b>Complete Data Visualization and Pre-processing Series with projects</b></a></p></blockquote><blockquote id="409a"><p><a href="https://readmedium.com/complete-python-and-projects-mega-compilation-7ec8f7adfe71?sk=ee0ecf43f23c6dd44dd35d984b3e5df4"><b>Complete Python Series with Projects</b></a></p></blockquote><blockquote id="67e0"><p><a href="https://readmedium.com/complete-advanced-python-with-projects-mega-compilation-part-6-729c1826032b?sk=7faffe20f8039fa57099f7a372b6d665"><b>Complete Advanced Python Series with Projects</b></a></p></blockquote><blockquote id="4ded"><p><a href="https://readmedium.com/my-list-of-kaggle-best-notebooks-topic-wise-data-science-and-machine-learning-part-2-84772863e9ae?sk=5ed02e419854a6c11add3ddc1e52947f"><b>Kaggle Best Notebooks that will teach you the most</b></a></p></blockquote><blockquote id="4b2e"><p><a href="https://medium.datadriveninvestor.com/the-complete-developers-guide-to-git-6a23125996e1?sk=e30479bbe713930ea93018e1a46d9185"><b>Complete Developers Guide to Git</b></a></p></blockquote><blockquote id="732e"><p><a href="https://readmedium.com/6-exceptional-github-repos-for-all-developers-part-1-21e8fa04e150?sk=9140b249af6fe73d45717185fad48962"><b>Exceptional Github Repos</b></a><b> — Part 1</b></p></blockquote><blockquote id="7079"><p><a href="https://readmedium.com/6-exceptional-github-repos-for-all-developers-part-2-3eec9a68c31c?sk=8e31d0eb7eb1d2d0bbbcecaa66bd4e7e"><b>Exceptional Github Repos</b></a><b> — Part 2</b></p></blockquote><blockquote id="d9c6"><p><a href="https://medium.datadriveninvestor.com/best-resources-for-data-science-and-machine-learning-full-list-5ceb9a2791bf?sk=cf85b2cef95560c58509877a794577ff"><b>All the Data Science and Machine Learning Resources</b></a></p></blockquote><blockquote id="b2cb"><p><a href="https://medium.datadriveninvestor.com/210-machine-learning-projects-with-source-code-that-you-can-build-today-721b035649e0?sk=da5f593572a0261a6314afad99a0356c"><b>210 Machine Learning Projects</b></a></p></blockquote><h2 id="9083">Tech Newsletter —</h2><blockquote id="f86c"><p>If you are interested, you can join my newsletter through which I send tech interview tips, techniques, patterns, hacks — Software Development, ML, Data Science, Startups and Technology projects to more than 30K readers. You can subscribe to <b>Tech Brew :</b></p></blockquote><div id="8d5c" class="link-block"> <a href="https://naina0405.substack.com/"> <div> <div> <h2>Ignito</h2> <div><h3>Data Science, ML, AI and more… Click to read Ignito, by Naina Chaturvedi, a Substack publication. Launched 7 months…</h3></div> <div><p>naina0405.substack.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*_ER1J-h50iqAjH70)"></div> </div> </div> </a> </div><p id="eb48"><b><i>For Python Projects —</i></b></p><div id="22a4" class="link-block"> <a href="https://readmedium.com/complete-python-and-projects-mega-compilation-7ec8f7adfe71"> <div> <div> <h2>Complete Python And Projects — Mega Compilation</h2> <div><h3>Everything that you need to know in Python with Projects…</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*NnCSMN6etFjjw4Jn.jpg)"></div> </div> </div> </a> </div><div id="471c" class="link-block"> <a href="https://medium.datadriveninvestor.com/analyzing-video-using-python-opencv-and-numpy-5471cab200c4"> <div> <div> <h2>Analyzing Video using Python, OpenCV and NumPy</h2> <div><h3>With Code Implementation…</h3></div> <div><p>medium.datadriveninvestor.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*PYNCDW3IXI2BcT5f.jpg)"></div> </div> </div> </a> </div><p id="f199"><b><i>For complete 60 days of Data Science and ML : Day 1 — Day 60 : Quick Recap of 60 days of Data Science and ML</i></b></p><div id="9d77" class="link-block"> <a href="https://readmedium.com/day-1-day-60-quick-recap-of-60-days-of-data-science-and-ml-6fc021643d1"> <div> <div> <h2>Day 1 — Day 60 : Quick Recap of 60 days of Data Science and ML</h2> <div><h3>Connect the ML dots…</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*ZfJ1yKIzPLGABAI_.png)"></div> </div> </div> </a> </div><p id="1253"><b><i>Follow for more updates. Stay tuned and keep coding!</i></b></p><h1 id="21c3">For other projects, tune to —</h1><p id="b31f"><b>Build Machine Learning Pipelines( With Code)</b></p><div id="5b37" class="link-block"> <a href="https://medium.datadriveninvestor.com/build-machine-learning-pipelines-with-code-part-1-bd3ed7152124"> <div> <div> <h2>Build Machine Learning Pipelines( With Code) — Part 1</h2> <div><h3>Complete implementation…</h3></div> <div><p>medium.datadriveninvestor.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*KdToBD8RDMBH4jXM.png)"></div> </div> </div> </a> </div><p id="946c"><b>Recurrent Neural Network with Keras</b></p><div id="f317" class="link-block"> <a href="https://medium.datadriveninvestor.com/recurrent-neural-network-with-keras-b5b5f6fe5187"> <div> <div> <h2>Recurrent Neural Network with Keras</h2> <div><h3>Project Implementation and cheatsheet…</h3></div> <div><p>medium.datadriveninvestor.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*xs3Dya3qQBx6IU7C.png)"></div> </div> </div> </a> </div><p id="ec53"><b>Clustering Geolocation Data in Python using DBSCAN and K-Means</b></p><div id="2b3e" class="link-block"> <a href="https://medium.datadriveninvestor.com/clustering-geolocation-data-in-python-using-dbscan-and-k-means-3705d9f44522"> <div> <div> <h2>Clustering Geolocation Data in Python using DBSCAN and K-Means</h2> <div><h3>Project Implementation…</h3></div> <div><p>medium.datadriveninvestor.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*0uPCZnohdaPCO4NN.png)"></div> </div> </div> </a> </div><p id="a29c"><b>Facial Expression Recognition using Keras</b></p><div id="ccaa" class="link-block"> <a href="https://medium.datadriveninvestor.com/facial-expression-recognition-using-keras-cbdd661a0a54"> <div> <div> <h2>Facial Expression Recognition using Keras</h2> <div><h3>Project Implementation…</h3></div> <div><p>medium.datadriveninvestor.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*CGch7hzdjg1fpgKy.jpg)"></div> </div> </div> </a> </div><p id="0db7"><b>Hyperparameter Tuning with Keras Tuner</b></p><div id="6dff" class="link-block"> <a href="https://medium.datadriveninvestor.com/hyperparameter-tuning-with-keras-tuner-3a609d3fd85b"> <div> <div> <h2>Hyperparameter Tuning with Keras Tuner</h2> <div><h3>Project Implementation….</h3></div> <div><p>medium.datadriveninvestor.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*jlaEz8AZaptNWHEr.png)"></div> </div> </div> </a> </div><p id="fed8"><b>Custom Layers in Keras</b></p><div id="e4fd" class="link-block"> <a href="https://medium.datadriveninvestor.com/custom-layers-in-keras-de5f793217aa"> <div> <div> <h2>Custom Layers in Keras</h2> <div><h3>Code implementation …</h3></div> <div><p>medium.datadriveninvestor.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*1IH67KJadqeqeO01.png)"></div> </div> </div> </a> </div></article></body>

Day 8 of System Design Case Studies Series : Design URL shortener, Agoda, Razorpay, Apple Music, CricHD, Alibaba, Substack, Instant Messenger, Hacker News, Facebook Timeline, Online Poker Game, Amazon Locker

Complete Design with examples

Pic copyright and credits : Naina Chaturvedi

Hello peeps! Welcome to Day 8 of System Design Case studies series where we will design URL Shortener, Agoda, Razorpay, Apple Music, CricHD, Alibaba, Substack, Instant Messenger, Hacker News, Facebook Timeline, Online Poker Game and Amazon Locker.

This post has system design for ( scroll till the end of the post) —

Design URL Shortener

Design Agoda

Design Razorpay

Design Apple Music

Design CricHD

Design Alibaba

Design Substack

Design Instant Messenger

Design Hacker News

Design Facebook Timeline

Design Online Poker Game

Design Amazon Locker

Note : Please read System Design Important Terms you MUST know and Most Important System Design basics before reading this post.

Projects Videos —

All the projects, data structures, SQL, algorithms, system design, Data Science and ML , Data Analytics, Data Engineering, , Implemented Data Science and ML projects, Implemented Data Engineering Projects, Implemented Deep Learning Projects, Implemented Machine Learning Ops Projects, Implemented Time Series Analysis and Forecasting Projects, Implemented Applied Machine Learning Projects, Implemented Tensorflow and Keras Projects, Implemented PyTorch Projects, Implemented Scikit Learn Projects, Implemented Big Data Projects, Implemented Cloud Machine Learning Projects, Implemented Neural Networks Projects, Implemented OpenCV Projects,Complete ML Research Papers Summarized, Implemented Data Analytics projects, Implemented Data Visualization Projects, Implemented Data Mining Projects, Implemented Natural Leaning Processing Projects, MLOps and Deep Learning, Applied Machine Learning with Projects Series, PyTorch with Projects Series, Tensorflow and Keras with Projects Series, Scikit Learn Series with Projects, Time Series Analysis and Forecasting with Projects Series, ML System Design Case Studies Series videos will be published on our youtube channel ( just launched).

Subscribe today!

Solved System Design Case Studies — In depth

Design Instagram

Design Messenger App

Design Twitter

Design URL Shortener

Design Dropbox

Design Youtube

Design API Rate Limiter

Design Web Crawler

Design Facebook’s Newsfeed

Design Yelp

Design Uber

Design Tinder

Design Tiktok

Design Whatsapp

Most Popular System Design Questions

Mega Compilation : Solved System Design Case studies

We will be discussing in depth -

Pre-requisite to this post -

Complete System Design Series — Important Concepts that you should know before starting the Case studies

1. System design basics

2. Horizontal and vertical scaling

3. Load balancing and Message queues

4. High level design and low level design, Consistent Hashing, Monolithic and Microservices architecture

5. Caching, Indexing, Proxies

6. Networking, How Browsers work, Content Network Delivery ( CDN)

7. Database Sharding, CAP Theorem, Database schema Design

8. Concurrency, API, Components + OOP + Abstraction

9. Estimation and Planning, Performance

10. Map Reduce, Patterns and Microservices

11. SQL vs NoSQL and Cloud

12. Most Popular System Design Questions

13. System Design Template — How to solve any System Design Question

Github —

Day 1 of System Design Case Studies can be found below-

Day 2 of System Design Case Studies can be found below-

Day 3 of System Design Case Studies can be found below-

Day 4 of System Design Case Studies can be found below-

What is URL shortener

Pic credits : mediawiki

URL shortener is a service which —

  1. Takes a long URL and creates a shorter URL
  2. Takes Short URL and redirects the user to the original Long URL

Examples — goo.gl, tinyurl etc

Shortened URL should be random and unique. It should be a combination of characters ( A-Z, a-z) and numbers ( 0–9).

Some key components of URL shortener ( functionalities):

  1. Shortening algorithm: The URL shortener would need to have a way to convert long URLs into shorter, unique codes. This could be achieved using a hash function or a base-conversion algorithm.
  2. Redirection: The short code generated by the shortening algorithm needs to be associated with the original URL, and the short code should redirect the user to the original URL when clicked.
  3. URL storage: The original URLs and the associated short codes need to be stored in a database, and should be designed to handle a large number of records.
  4. User accounts: Users should have the ability to create an account and have their own custom short URLs.
  5. Analytics: The URL shortener would need to track usage and engagement metrics, including click-through rate and number of clicks for each shortened link.
  6. Security: The shortener would need to be designed with security in mind, to protect user data and prevent unauthorized access.
  7. Scalability: The URL shortener needs to be able to handle a large number of requests and high traffic loads. This would involve designing the application to be scalable, including using technologies such as load balancers and distributed systems.
  8. API: The URL shortener should provide an API to enable developers to shorten and expand URLs programmatically.
  9. Custom short domains: The shortener should allow users to use their own custom short domains to shorten the URLs.
  10. Link Expiration: The shortener should allow users to set expiration date for shortened links.

Let’s understand 3 more concepts which will be used later in the detailed design.

Zookeeper

It’s a component that retains the count ( similar to apache kafka) and assign random number ranges for each server.

Pic credits : Quora

In a distributed system, ZooKeeper is a software service that acts as a centralized coordination service for distributed systems. It allows for maintaining configuration information, naming, providing distributed synchronization, and providing group services. The function of ZooKeeper is to coordinate and manage the distributed systems, by providing a simple and reliable interface for distributed applications to access and update the configuration information, and to coordinate and synchronize the activities of the distributed systems. The role of a ZooKeeper is similar to a traditional zookeeper, in that it is responsible for maintaining the overall health and well-being of the distributed system, and ensuring that it runs smoothly and efficiently.

A simple ZooKeeper client in Python using the kazoo library:

import time
from kazoo.client import KazooClient
zk = KazooClient(hosts='127.0.0.1:2181')
zk.start()
# Create a node in ZooKeeper
zk.create("/myapp/node1", b"data1", makepath=True)
# Read the data stored in the node
data, stat = zk.get("/myapp/node1")
print("Node data:", data.decode())
# Update the data stored in the node
zk.set("/myapp/node1", b"data2")
data, stat = zk.get("/myapp/node1")
print("Updated node data:", data.decode())
# Delete the node
zk.delete("/myapp/node1")
# Check if the node exists
if zk.exists("/myapp/node1"):
    print("Node exists")
else:
    print("Node does not exist")
zk.stop()

In this example, we start by creating a connection to the ZooKeeper server using the KazooClient class. We then create a node in ZooKeeper by calling the create method. The get method is used to read the data stored in the node, and the set method is used to update the data stored in the node. The delete method is used to delete the node, and the exists method is used to check if the node still exists. Finally, we close the connection to the ZooKeeper server by calling stop.

Base 62

Base 62 is an encoding scheme which uses 62 characters ( a-z, A-Z) and numbers (0–9) is 26+26+10 = 62.

Pic credits : codeproject

Base 62 is a numeral system that uses 62 as its base, rather than the common base of 10 used in the decimal system or base 16 used in the hexadecimal system. In base 62, there are 62 different digits or characters that can be used to represent numbers, rather than the 10 digits used in the decimal system. These 62 characters typically include the digits 0–9, the uppercase and lowercase letters of the English alphabet, and other characters such as +, /, or -. Using base 62 allows for a more compact representation of numbers, as fewer characters are needed to represent a given value than in base 10 or base 16. It is often used in shortening URL, encoding unique id and other similar use cases.

MD5 Hash

It’s a cryptographic hash algorithm which is used to generate 128 bit digest when a string of any length is input using the complex maths formula. It converts data into blocks of specific sizes.

Pic credits : systools

MD5 (Message-Digest algorithm 5) is a widely-used cryptographic hash function that produces a 128-bit (16-byte) hash value, typically expressed as a 32-digit hexadecimal number. It is a one-way function, meaning that it takes an input (or ‘message’) and returns a fixed-size string of characters, which is a ‘digest’ that is unique to the original input. The same input will always produce the same output, but even a small change to the input will produce a very different output.

Here’s an example of how to calculate the MD5 hash of a string in Python:

import hashlib
def get_md5_hash(data):
    md5 = hashlib.md5()
    md5.update(data.encode())
    return md5.hexdigest()
data = "Hello World!"
hash = get_md5_hash(data)
print("MD5 hash of '{}': {}".format(data, hash))

In this example, we first import the hashlib library and define a function get_md5_hash that takes a string as input and returns its MD5 hash. To calculate the hash, we create an instance of the md5 hash function from the hashlib library. We then use the update method to add the data to the hash function, and finally use the hexdigest method to get the hexadecimal representation of the hash. In this example, the output of the program is the MD5 hash of the string "Hello World!". Note that the update method expects the input data to be of type bytes, so we need to encode the input string to bytes using the encode method before passing it to update.

It is commonly used to verify the integrity of files, to ensure that a transferred file has been received without any errors, and to check for duplicates in a large data set. It is also used in various encryption and authentication protocols, such as storing hashed passwords in a database.

Important Features

Convert Long URL to Tiny URL

Convert Tiny URL into Long URL

Scaling Requirements — Capacity Estimation

Let’s say —

About ~80 Million URL’s are generated everyday.

Write operations per second —

80Million/24/3600 = 930 write operations per second

Let’ assume, read to write ratio is 8:1, then read operations per second —

930 * 8 = 7440 read operations per second

Average URL length is 90bytes

Storage Requirement —

80 Million * 90 = 7GB /day

No of records after 5 years —

80Million * 365 * 5 = 146 Billion

For next 5 years, the storage requirements would be —

90Bytes * 5 * 146 Billion = 65.7 TB

Data Model — ER requirements

User

User_id: Int

Username: String

Email : String

Date_of_creation: Datetime

Functionality —

Users should be able to shorten the url.

Users should be able to get the original url from the shortened url.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — —

URL table

short_url_id : Int

long_url_id : Int

short_url_text: String

Long_url_text: String

Functionality —

Store/compute the shorten url and long url.

Data Model

High Level Design

Assumptions /Considerations

  1. The shortened URL should be human readable
  2. Links will expire after 1 year ( inactivity)
  3. Hash function — to hash a long URL into a short URL from characters ( a-z, A-Z) and numbers (0–9) is 26+26+10 = 62
  4. Availability vs consistency : The system should be highly available.
  5. URL redirection must happen in real time with low latency
  6. Cache should follow 80% — 20% rule i.e 20% of URL’s generate 80% of traffic and these 20% URL are hot URL’s.
Pic copyright and credits : Naina Chaturvedi

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — -

Components

  • Mobile/Web based Clients : Users
  • Load Balancers : To allocate requests to designated Application server using consistent hashing
  • Application servers and Database servers
  • NoSQL Database and replicas : Cassandra ( Key Value Store)
  • Cache Server

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — -

Services

Key Generation service: To randomly generate 6 letters strings and store them into the database ( key — value). This will eliminate collision and duplications problems.

A microservice in Python that implements the functionality of a URL shortener:

import flask
import pymongo
app = flask.Flask(__name__)
# Connect to the database
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["url_shortener"]
urls = db["urls"]
# Define an endpoint for shortening a URL
@app.route("/shorten", methods=["POST"])
def shorten_url():
    # Retrieve the URL to be shortened from the request
    long_url = flask.request.form["long_url"]
    # Generate a unique identifier for the URL
    url_id = generate_unique_id()
    # Store the URL in the database
    urls.insert_one({"_id": url_id, "long_url": long_url})
    # Return the shortened URL
    return flask.jsonify({"short_url": f"http://localhost:5002/{url_id}"})
# Define an endpoint for resolving a shortened URL
@app.route("/<url_id>", methods=["GET"])
def resolve_url(url_id):
    # Retrieve the long URL from the database
    url = urls.find_one({"_id": url_id})
    # Return the long URL
    return flask.redirect(url["long_url"])
# Example usage
if __name__ == "__main__":
    app.run(port=5002)

In this example, the microservice provides two endpoints for the following operations: shortening a URL and resolving a shortened URL. The microservice uses MongoDB to store the URLs, and the unique identifier for each URL is generated using a generate_unique_id function (which is not shown in this code).

API Design

Implementation —

from flask import Flask, jsonify, request
import string
import random
import redis
app = Flask(__name__)
# Initialize Redis client
redis_client = redis.Redis(host='localhost', port=6379, db=0)
# Endpoint for shortening a URL
@app.route('/shorten', methods=['POST'])
def shorten_url():
    # Get URL from request
    url = request.json['url']
    
    # Generate short code
    short_code = generate_short_code()
    
    # Store short code and URL in Redis
    redis_client.set(short_code, url)
    
    # Return short URL
    short_url = request.host_url + short_code
    return jsonify({'short_url': short_url})
# Endpoint for redirecting a short URL to the original URL
@app.route('/<string:short_code>', methods=['GET'])
def redirect_url(short_code):
    # Get URL from Redis
    url = redis_client.get(short_code)
    
    # Redirect to original URL
    if url:
        return redirect(url.decode(), code=302)
    else:
        return jsonify({'message': 'Short code not found'})
# Helper function for generating a random short code
def generate_short_code():
    characters = string.ascii_letters + string.digits
    while True:
        short_code = ''.join(random.choice(characters) for i in range(6))
        if not redis_client.get(short_code):
            return short_code
if __name__ == '__main__':
    app.run(debug=True)

In this implementation, we have two endpoints:

  • /shorten (POST): This endpoint is used to shorten a URL. The URL is passed in the request body as a JSON object with the key "url". The endpoint generates a random short code and stores the short code and the original URL in Redis. It then returns the short URL as a JSON object with the key "short_url".
  • /<short_code> (GET): This endpoint is used to redirect a short URL to the original URL. The short code is passed as part of the endpoint URL. The endpoint retrieves the original URL from Redis and redirects the request to the original URL using a 302 redirect.

Shorten the link

  • Type : POST
  • POST:/data/shorten

Body{

long _url = “”

}

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — -

URL redirection

  • Type : GET
  • GET :api/data/shortURL

Here’s an example of a basic implementation of a URL shortener API in Python using the Flask framework:

from flask import Flask, request
import hashlib
import json
app = Flask(__name__)
# Create a database to store the mapping of short URLs to original URLs
short_to_long_url_mapping = {}
long_to_short_url_mapping = {}
# Define the hash function to generate a unique short URL
def get_short_url(long_url):
    # Use the SHA-256 hash function to generate a unique hash for the long URL
    hash = hashlib.sha256(long_url.encode()).hexdigest()[:6]
    # Return the shortened URL
    return "http://example.com/" + hash
# Route to handle URL shortening requests
@app.route("/shorten", methods=["POST"])
def shorten_url():
    # Extract the long URL from the request body
    long_url = request.get_json()["long_url"]
    # Check if the long URL has already been shortened
    if long_url in long_to_short_url_mapping:
        return json.dumps({"short_url": long_to_short_url_mapping[long_url]})
    # If the long URL has not been shortened, generate a new short URL
    short_url = get_short_url(long_url)
    # Store the mapping of the short URL to the long URL
    short_to_long_url_mapping[short_url] = long_url
    long_to_short_url_mapping[long_url] = short_url
    # Return the short URL
    return json.dumps({"short_url": short_url})
# Route to handle URL redirects
@app.route("/<short_url>")
def redirect_url(short_url):
    # Look up the long URL associated with the short URL
    long_url = short_to_long_url_mapping.get(short_url)
    # If the short URL is not in the database, return an error
    if not long_url:
        return "Error: URL not found", 404
    # Otherwise, redirect to the long URL
    return redirect(long_url)
if __name__ == "__main__":
    app.run(debug=True)

Basic Low Level Design

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

class URLShortener {
    private Map<String, String> shortToOriginal;
    private Map<String, String> originalToShort;
    private static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static final int SHORT_LENGTH = 6;

    public URLShortener() {
        this.shortToOriginal = new HashMap<>();
        this.originalToShort = new HashMap<>();
    }

    public String shortenURL(String originalURL) {
        if (originalToShort.containsKey(originalURL)) {
            return originalToShort.get(originalURL);
        } else {
            String shortURL = generateShortURL();
            shortToOriginal.put(shortURL, originalURL);
            originalToShort.put(originalURL, shortURL);
            return shortURL;
        }
    }

    public String getOriginalURL(String shortURL) {
        return shortToOriginal.get(shortURL);
    }

    private String generateShortURL() {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();

        for (int i = 0; i < SHORT_LENGTH; i++) {
            int index = random.nextInt(CHARACTERS.length());
            sb.append(CHARACTERS.charAt(index));
        }

        return sb.toString();
    }
}

public class URLShortenerApp {
    public static void main(String[] args) {
        URLShortener urlShortener = new URLShortener();

        // Shorten URLs
        String shortURL1 = urlShortener.shortenURL("https://www.example.com/page1");
        String shortURL2 = urlShortener.shortenURL("https://www.example.com/page2");
        String shortURL3 = urlShortener.shortenURL("https://www.example.com/page3");

        // Retrieve original URLs
        String originalURL1 = urlShortener.getOriginalURL(shortURL1);
        String originalURL2 = urlShortener.getOriginalURL(shortURL2);
        String originalURL3 = urlShortener.getOriginalURL(shortURL3);

        System.out.println("Original URL for " + shortURL1 + ": " + originalURL1);
        System.out.println("Original URL for " + shortURL2 + ": " + originalURL2);
        System.out.println("Original URL for " + shortURL3 + ": " + originalURL3);
    }
}

Complete Detailed Design

( Zoom it)

Pic copyright and credits : Naina Chaturvedi

Code

URL shortening is a technique where a long URL is shortened to a shorter version that redirects to the original URL. This is useful in situations where long URLs are difficult to share or remember, such as on social media platforms or in text messages.

In this task, we will implement a URL shortener using Python.

To implement a URL shortener, we will make use of a third-party library called pyshorteners. This library provides an easy-to-use API for shortening and expanding URLs. To install this library, you can use pip:

pip install pyshorteners

Here is the Python code for a URL shortener that takes a long URL and creates a shorter URL:

import pyshorteners
# Create an instance of the pyshorteners.Shortener() class
shortener = pyshorteners.Shortener()
# Long URL to be shortened
long_url = "https://www.example.com/a/very/long/url"
# Shorten the URL
short_url = shortener.tinyurl.short(long_url)
# Print the shortened URL
print("Short URL:", short_url)

In this code, we first import the pyshorteners library and create an instance of the Shortener() class. We then define the long URL that we want to shorten, and call the short() method of the Shortener() instance to generate a shortened URL. Finally, we print the shortened URL.

To redirect a user from a short URL to the original long URL, we can make use of the expand() method of the Shortener() class. Here is the code for redirecting a user from a short URL to the original long URL:

import pyshorteners
# Create an instance of the pyshorteners.Shortener() class
shortener = pyshorteners.Shortener()
# Short URL to be expanded
short_url = "https://tinyurl.com/abc123"
# Expand the URL
long_url = shortener.expand(short_url)
# Redirect the user to the long URL
print("Redirecting to:", long_url)

In this code, we first import the pyshorteners library and create an instance of the Shortener() class. We then define the short URL that we want to expand, and call the expand() method of the Shortener() instance to retrieve the original long URL. Finally, we print the long URL and redirect the user to that URL.

More on URL shortener System Design —

URL Shortening Algorithm:

To generate unique and short URLs, we can use a combination of alphanumeric characters. One commonly used technique is base62 encoding, which uses the characters [A-Z], [a-z], and [0–9] to represent the URL.

Here’s an example of a URL shortening algorithm using base62 encoding in Python:

import string
def shorten_url(url):
    characters = string.ascii_letters + string.digits
    base = len(characters)
    short_url = ""
    # Convert the URL into a unique integer
    url_hash = hash(url)
    # Convert the integer into a base62 representation
    while url_hash > 0:
        url_hash, remainder = divmod(url_hash, base)
        short_url = characters[remainder] + short_url
    return short_url
# Example usage
long_url = "https://www.example.com/some/long/url"
short_url = shorten_url(long_url)
print(short_url)

URL Redirection:

To handle URL redirection from the shortened URL to the original URL, we can use a lookup mechanism that maps the shortened URL to the original URL in a database.

Here’s an example of a URL redirection system in Python:

import sqlite3
from flask import Flask, redirect, abort
app = Flask(__name__)
db = sqlite3.connect("urls.db")  # Assuming a SQLite database
@app.route("/<short_url>")
def redirect_url(short_url):
    # Look up the original URL in the database
    cursor = db.cursor()
    cursor.execute("SELECT original_url FROM urls WHERE short_url=?", (short_url,))
    result = cursor.fetchone()
    if result:
        original_url = result[0]
        return redirect(original_url, code=301)  # Perform a 301 redirect
    else:
        abort(404)  # Short URL not found
if __name__ == "__main__":
    app.run()

Link Analytics and Tracking:

To collect and analyze click data for link analytics, we can record each click event and associated information such as the referring URL and geographic information in a database.

Here’s an example of a link analytics and tracking system in Python:

import sqlite3
db = sqlite3.connect("analytics.db")  # Assuming a SQLite database
def track_click(short_url, referring_url, country):
    # Save the click event in the database
    cursor = db.cursor()
    cursor.execute("INSERT INTO clicks (short_url, referring_url, country) VALUES (?, ?, ?)",
                   (short_url, referring_url, country))
    db.commit()
# Example usage
short_url = "abc123"
referring_url = "https://www.referrer.com"
country = "US"
track_click(short_url, referring_url, country)

Scalability and Performance:

Horizontal and Vertical Scaling:

Horizontal scaling involves adding more servers or instances to handle increased traffic and URL generation. It can be achieved by distributing the workload across multiple servers.

Vertical scaling involves increasing the resources (CPU, memory, etc.) of an existing server to handle increased traffic and URL generation.

# Horizontal scaling example using multiple server instances
def handle_request(request):
    # Handle request logic
    pass
# Vertical scaling example using multithreading
import threading
def handle_request(request):
    # Handle request logic
    pass
def start_server():
    # Start the server
    pass
# Create multiple threads to handle requests concurrently
for i in range(5):
    t = threading.Thread(target=start_server)
    t.start()

Caching Mechanisms:

Caching mechanisms improve system performance by storing frequently accessed data in a cache, reducing the need to fetch the data from the original source repeatedly. In-memory caching and content delivery networks (CDNs) are common caching techniques.

# In-memory caching example using Python dictionary
cache = {}
def get_from_cache(key):
    if key in cache:
        return cache[key]
    else:
        # Fetch data from the database
        data = fetch_from_database(key)
        cache[key] = data
        return data
# CDN caching example using Flask-Caching extension
from flask import Flask
from flask_caching import Cache
app = Flask(__name__)
cache = Cache(app, config={'CACHE_TYPE': 'simple'})
@app.route('/data/<key>')
@cache.cached(timeout=300)  # Cache the response for 300 seconds (5 minutes)
def get_data(key):
    # Fetch data from the database
    data = fetch_from_database(key)
    return data
if __name__ == '__main__':
    app.run()

Load Balancing, Sharding, and Replication:

Load balancing distributes incoming requests across multiple servers to evenly distribute the load and prevent any single server from being overwhelmed.

Sharding involves partitioning the data across multiple database instances to distribute the load and improve performance.

Replication involves creating copies of the data on multiple servers to ensure fault tolerance and improve read performance.

Implementation of load balancing, sharding, and replication may depend on the specific technologies and frameworks used. Here’s an example of load balancing using a reverse proxy server like Nginx:

# Nginx configuration example for load balancing
http {
    upstream backend {
        server backend1.example.com;
        server backend2.example.com;
        server backend3.example.com;
    }
    server {
        listen 80;
        location / {
            proxy_pass http://backend;
        }
    }
}

Data Storage and Persistence:

Designing systems to store and retrieve shortened URLs and their mappings:

# Example using a relational database (SQLite)
import sqlite3
def store_url_mapping(short_url, original_url):
    conn = sqlite3.connect('url_shortener.db')
    cursor = conn.cursor()
    cursor.execute('INSERT INTO url_mappings (short_url, original_url) VALUES (?, ?)', (short_url, original_url))
    conn.commit()
    conn.close()
def get_original_url(short_url):
    conn = sqlite3.connect('url_shortener.db')
    cursor = conn.cursor()
    cursor.execute('SELECT original_url FROM url_mappings WHERE short_url = ?', (short_url,))
    result = cursor.fetchone()
    conn.close()
    return result[0] if result else None

Choosing appropriate database technologies (e.g., relational, NoSQL) for efficient data storage:

# Example using a NoSQL database (MongoDB)
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/')
db = client['url_shortener']
def store_url_mapping(short_url, original_url):
    db.url_mappings.insert_one({'short_url': short_url, 'original_url': original_url})
def get_original_url(short_url):
    result = db.url_mappings.find_one({'short_url': short_url})
    return result['original_url'] if result else None

Handling data consistency and durability:

# Example using transaction for data consistency in a relational database (SQLite)
import sqlite3
def store_url_mapping(short_url, original_url):
    conn = sqlite3.connect('url_shortener.db')
    cursor = conn.cursor()
    try:
        conn.execute('BEGIN')
        cursor.execute('INSERT INTO url_mappings (short_url, original_url) VALUES (?, ?)', (short_url, original_url))
        conn.commit()
    except Exception as e:
        conn.execute('ROLLBACK')
        raise e
    finally:
        conn.close()

Customization and Vanity URLs:

Implementing features to allow users to customize their shortened URLs:

# Example allowing users to customize their shortened URLs
def create_custom_short_url(custom_alias, original_url):
    # Check if the custom alias is available
    if is_custom_alias_available(custom_alias):
        store_url_mapping(custom_alias, original_url)
        return custom_alias
    else:
        # Handle conflict or provide alternative options
        return generate_alternative_short_url()
def is_custom_alias_available(custom_alias):
    # Check if the custom alias is available in the database
    return not get_original_url(custom_alias)
def generate_alternative_short_url():
    # Generate alternative short URL using a different algorithm or approach
    pass

Handling reserved keywords, restrictions, and conflicts:

# Example handling reserved keywords and restrictions
RESERVED_KEYWORDS = ['admin', 'settings', 'dashboard']
def is_custom_alias_available(custom_alias):
    # Check if the custom alias is available in the database and not a reserved keyword
    return not get_original_url(custom_alias) and custom_alias not in RESERVED_KEYWORDS

Enabling vanity URLs for branding purposes:

# Example allowing vanity URLs for branding purposes
def create_vanity_url(original_url, vanity_domain):
    vanity_url = generate_vanity_url(vanity_domain)
    store_url_mapping(vanity_url, original_url)
    return vanity_url
def generate_vanity_url(vanity_domain):
    # Generate a vanity URL based on the provided vanity domain and other criteria
    pass

User Management and Authentication:

Implementing user registration and authentication:

# Example implementing user registration and authentication
import bcrypt

def register_user(username, password):
    # Hash the password before storing it in the database
    hashed_password = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
    store_user(username, hashed_password)

def authenticate_user(username, password):
    # Retrieve the user's hashed password from the database
    hashed_password = get_user_password(username)

    if hashed_password and bcrypt.checkpw(password.encode(), hashed_password.encode()):
        # Passwords match, authentication successful
        return True
    else:
        # Invalid username or password
        return False

Handling user profiles, permissions, and access controls:

# Example handling user profiles, permissions, and access controls
def create_user_profile(user_id, profile_data):
    # Store the user's profile data in the database
    store_user_profile(user_id, profile_data)

def get_user_permissions(user_id):
    # Retrieve the user's permissions from the database
    return get_permissions(user_id)

def has_permission(user_id, permission):
    # Check if the user has the specified permission
    user_permissions = get_user_permissions(user_id)
    return permission in user_permissions

Integrating with third-party authentication providers (e.g., OAuth):

# Example integrating with third-party authentication providers using OAuth
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

def authenticate_with_oauth(client_id, client_secret, oauth_token_url):
    client = BackendApplicationClient(client_id=client_id)
    oauth = OAuth2Session(client=client)
    token = oauth.fetch_token(token_url=oauth_token_url, client_id=client_id, client_secret=client_secret)

    # Access protected resources using the obtained token
    response = oauth.get('https://api.example.com/protected_resource')
    return response.json()

API Design and Integration:

Designing user-friendly APIs for integrating the URL shortener service:

# Example designing user-friendly APIs using Flask framework
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/shorten', methods=['POST'])
def shorten_url():
    original_url = request.form['url']
    short_url = shorten(original_url)
    return jsonify({'short_url': short_url})
@app.route('/analytics', methods=['GET'])
def get_link_analytics():
    short_url = request.args.get('short_url')
    link_analytics = get_link_analytics(short_url)
    return jsonify(link_analytics)
@app.route('/redirect/<short_url>', methods=['GET'])
def redirect_url(short_url):
    original_url = get_original_url(short_url)
    if original_url:
        # Perform redirection
        return redirect(original_url, code=301)
    else:
        # Handle invalid or expired URLs
        return jsonify({'error': 'Invalid or expired URL'})
if __name__ == '__main__':
    app.run()

Handling API authentication, rate limiting, and data access controls:

# Example handling API authentication, rate limiting, and data access controls using Flask framework
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/shorten', methods=['POST'])
@authenticate_api_request
@rate_limit_exceeded
def shorten_url():
    original_url = request.form['url']
    short_url = shorten(original_url)
    return jsonify({'short_url': short_url})
@app.route('/analytics', methods=['GET'])
@authenticate_api_request
@rate_limit_exceeded
def get_link_analytics():
    short_url = request.args.get('short_url')
    link_analytics = get_link_analytics(short_url)
    return jsonify(link_analytics)
@app.route('/redirect/<short_url>', methods=['GET'])
def redirect_url(short_url):
    original_url = get_original_url(short_url)
    if original_url:
        # Perform redirection
        return redirect(original_url, code=301)
    else:
        # Handle invalid or expired URLs
        return jsonify({'error': 'Invalid or expired URL'})
if __name__ == '__main__':
    app.run()

Providing comprehensive documentation and SDKs for developers:

# Example providing comprehensive documentation and SDKs for developers
# You can use tools like Swagger or Flask-RESTful to generate API documentation
# Documentation for API endpoints and their functionalities
"""
POST /shorten
    Description: Shortens a given URL.
    Parameters:
        - url: The original URL to be shortened.
    Returns:
        - short_url: The shortened URL.
GET /analytics
    Description: Retrieves analytics data for a given shortened URL.
    Parameters:
        - short_url: The shortened URL.
    Returns:
        - link_analytics: Analytics data for the shortened URL.
GET /redirect/<short_url>
    Description: Performs a redirection to the original URL associated with the given shortened URL.
    Parameters:
        - short_url: The shortened URL.
    Returns:
        - Redirects to the original URL or returns an error if the URL is invalid or expired.
"""
# SDK for integrating with the URL shortener service
class URLShortenerClient:
    def __init__(self, base_url, api_key):
        self.base_url = base_url
        self.api_key = api_key
    def shorten_url(self, original_url):
        # Implementation of the SDK function to shorten a URL
        endpoint = '/shorten'
        headers = {'Authorization': self.api_key}
        data = {'url': original_url}
        response = requests.post(self.base_url + endpoint, headers=headers, data=data)
        return response.json()
    def get_link_analytics(self, short_url):
        # Implementation of the SDK function to retrieve link analytics
        endpoint = '/analytics'
        headers = {'Authorization': self.api_key}
        params = {'short_url': short_url}
        response = requests.get(self.base_url + endpoint, headers=headers, params=params)
        return response.json()
    def redirect_url(self, short_url):
        # Implementation of the SDK function to perform URL redirection
        endpoint = '/redirect/' + short_url
       

Error Handling and Monitoring:

Designing error handling mechanisms for unexpected scenarios involves identifying potential errors and exceptions that can occur in the URL shortener system and implementing strategies to handle them effectively. This includes proper error messages, logging error details for debugging purposes, and providing fallback mechanisms in case of failures.

Implementing logging and monitoring systems is crucial for system health and performance. Logging allows capturing important events, errors, and informational messages that occur during the operation of the system. Monitoring systems help track the system’s performance metrics, such as response time, throughput, and resource utilization, to identify bottlenecks and optimize the system.

Implementing alerts and notifications is important to ensure prompt actions in case of critical errors or system downtime. This can involve sending notifications via email, SMS, or other communication channels to the system administrators or relevant stakeholders.

Here’s an example of implementing error handling, logging, and monitoring using Python’s logging module:

import logging
# Configure the logger
logging.basicConfig(filename='url_shortener.log', level=logging.ERROR, format='%(asctime)s %(levelname)s %(message)s')
def shorten_url(url):
    try:
        # Code for shortening the URL
        # ...
        return short_url
    except Exception as e:
        logging.error('An error occurred while shortening the URL: %s', str(e))
        return None
def redirect_url(short_url):
    try:
        # Code for redirecting to the original URL
        # ...
        return original_url
    except Exception as e:
        logging.error('An error occurred while redirecting the URL: %s', str(e))
        return None
def monitor_system():
    # Code for monitoring system health and performance
    # ...
def send_alert(message):
    # Code for sending alerts and notifications
    # ...
# Example usage
short_url = shorten_url('https://www.example.com')
if short_url is None:
    send_alert('Error occurred while shortening the URL')
original_url = redirect_url('abc123')
if original_url is None:
    send_alert('Error occurred while redirecting the URL')
monitor_system()

Error Handling and Monitoring section, as well as the Compliance and Legal Considerations section:

import logging
import smtplib
# Configure the logger
logging.basicConfig(filename='url_shortener.log', level=logging.ERROR, format='%(asctime)s %(levelname)s %(message)s')
def shorten_url(url):
    try:
        # Code for shortening the URL
        # ...
        return short_url
    except Exception as e:
        logging.error('An error occurred while shortening the URL: %s', str(e))
        return None
def redirect_url(short_url):
    try:
        # Code for redirecting to the original URL
        # ...
        return original_url
    except Exception as e:
        logging.error('An error occurred while redirecting the URL: %s', str(e))
        return None
def monitor_system():
    # Code for monitoring system health and performance
    # ...
def send_alert(message):
    # Code for sending alerts and notifications
    try:
        # Code for sending email alert
        smtp_server = 'smtp.example.com'
        sender_email = 'alerts@example.com'
        receiver_email = 'admin@example.com'
        subject = 'URL Shortener Alert'
        body = message
        email_message = f"Subject: {subject}\n\n{body}"
        with smtplib.SMTP(smtp_server) as server:
            server.sendmail(sender_email, receiver_email, email_message)
    except Exception as e:
        logging.error('An error occurred while sending an alert: %s', str(e))
def handle_error_and_alert():
    # Example usage
    short_url = shorten_url('https://www.example.com')
    if short_url is None:
        send_alert('Error occurred while shortening the URL')
    original_url = redirect_url('abc123')
    if original_url is None:
        send_alert('Error occurred while redirecting the URL')
    monitor_system()
def handle_compliance():
    # Code for handling compliance and legal considerations
    # ...
# Example usage
handle_error_and_alert()
handle_compliance()

System Design — Agoda

We will be discussing in depth -

Pic credits : Pinterest

What is Agoda

Agoda is a prominent online travel booking platform that connects travelers with a vast selection of accommodation options worldwide. It offers a user-friendly interface for searching, booking, and managing hotel reservations, vacation rentals, flights, and other travel-related services.

Important Features

  • Search and Filtering: Agoda provides a comprehensive search functionality to allow users to find suitable accommodations based on their preferences, such as location, price range, amenities, and user ratings.
  • User Profiles and Personalization: Registered users can create profiles, save favorite properties, and receive personalized recommendations based on their browsing and booking history.
  • Booking and Payment: Agoda enables users to make secure bookings and facilitates various payment methods to ensure a seamless and convenient transaction experience.
  • Reviews and Ratings: Users can read and submit reviews and ratings for properties, helping others make informed decisions.
  • Multi-Language and Multi-Currency Support: Agoda supports multiple languages and currencies to cater to a diverse global user base.

Scaling Requirements — Capacity Estimation

Let’s assume —

Total number of users: 100 million

Daily active users (DAU): 20 million

Number of accommodations booked by user/day: 2

Total number of accommodations booked per day: 40 million accommodations/day

Since the system is read-heavy, let’s assume the read-to-write ratio to be 100:1.

Total number of accommodations listed per day = 1/100 * 40 million = 400,000 accommodations/day

Storage Estimation:

Let’s assume an average size of each accommodation listing to be 1 MB.

Total Storage per day: 400,000 * 1 MB = 400 GB/day

For the next 3 years, 400 GB * 365 * 3 = 438.3 TB

Requests per second: 40 million / (24 hours * 3600 seconds) = 462 requests/second

Horizontal Scalability: The architecture should be able to scale horizontally by adding more servers or instances to distribute the load and handle increased user demand.

Caching: Implementing a caching layer can help improve performance and reduce database load by storing frequently accessed data in memory.

Load Balancing: Utilizing load balancers will distribute incoming traffic across multiple servers, ensuring optimal resource utilization and preventing bottlenecks.

Database Scaling: The data storage layer should support horizontal scaling to handle the increasing volume of user and property data efficiently.

Data Model — ER requirements

Users:

  • Fields: UserID, Username, Email, Password

Properties:

  • Fields: PropertyID, Name, Location, Price, Amenities

Bookings:

  • Fields: BookingID, UserID, PropertyID, CheckInDate, CheckOutDate, Guests

Reviews:

  • Fields: ReviewID, PropertyID, UserID, Rating, Comment

Relationships:

  1. Users can have multiple Bookings (one-to-many relationship).
  2. Properties can have multiple Reviews (one-to-many relationship).
  3. Users can post multiple Reviews (one-to-many relationship).

High Level Design

Assumptions:

  1. The system is read-heavy with more users searching for properties than posting.
  2. Availability and reliability are more important than consistency.
  3. The system should handle a large number of concurrent requests and provide low latency.

Main Components:

  1. Mobile Client: Represents the users accessing Agoda through mobile devices.
  2. Application Servers: Handle user requests, perform business logic, and interact with other components.
  3. Load Balancer: Routes and distributes incoming requests to application servers.
  4. Cache (Memcache): Stores frequently accessed data to improve performance.
  5. CDN: Content Delivery Network to optimize latency and throughput.
  6. Database: Stores data using a NoSQL database, ensuring high reliability.
  7. Storage (e.g., HDFS or Amazon S3): Stores and retrieves property photos.

Services:

  1. Search and Filtering Service: Provides search functionality for users to find suitable properties based on location, price range, amenities, etc.
  2. User Management Service: Handles user registration, authentication, and profile management.
  3. Booking and Payment Service: Facilitates secure property bookings and payment transactions.
  4. Review Service: Manages the submission and retrieval of property reviews and ratings.
  5. Feed Generation Service: Generates personalized feeds for users based on their preferences and browsing history.
class SearchAndFilterService:
    def search_properties(self, location, price_range, amenities):
        filtered_properties = []
        for property in properties:
            if property.location == location and \
               property.price >= price_range[0] and property.price <= price_range[1] and \
               all(amenity in property.amenities for amenity in amenities):
                filtered_properties.append(property)
        return filtered_properties


class UserManagementService:
    def register_user(self, user):
        # Logic for user registration
        users.append(user)

    def authenticate_user(self, username, password):
        for user in users:
            if user.username == username and user.password == password:
                return True
        return False

    def update_profile(self, user_id, new_data):
        for user in users:
            if user.user_id == user_id:
                # Update user profile data
                user.username = new_data.get('username', user.username)
                user.password = new_data.get('password', user.password)
                # Update other user attributes
                break


class BookingAndPaymentService:
    def create_booking(self, user_id, property_id, check_in_date, check_out_date, guests):
        booking_id = len(bookings) + 1
        booking = Booking(booking_id, user_id, property_id, check_in_date, check_out_date, guests)
        bookings.append(booking)
        return booking_id

    def make_payment(self, booking_id, payment_info):
        for booking in bookings:
            if booking.booking_id == booking_id:
                # Process payment using payment_info
                break


class ReviewService:
    def submit_review(self, user_id, property_id, rating, comment):
        review_id = len(reviews) + 1
        review = Review(review_id, user_id, property_id, rating, comment)
        reviews.append(review)

    def get_reviews(self, property_id):
        property_reviews = []
        for review in reviews:
            if review.property_id == property_id:
                property_reviews.append(review)
        return property_reviews


class FeedGenerationService:
    def generate_feed(self, user_id):
        user_feed = []
        user_preferences = get_user_preferences(user_id)
        for property in properties:
            if property.location in user_preferences['locations'] and \
               property.price <= user_preferences['max_price'] and \
               any(amenity in property.amenities for amenity in user_preferences['amenities']):
                user_feed.append(property)
        return user_feed


# Example usage of the services
search_service = SearchAndFilterService()
filtered_properties = search_service.search_properties("New York", [100, 200], ["WiFi", "Pool"])

user_service = UserManagementService()
user_service.register_user(user)

booking_service = BookingAndPaymentService()
booking_id = booking_service.create_booking(user_id, property_id, check_in_date, check_out_date, guests)

review_service = ReviewService()
review_service.submit_review(user_id, property_id, rating, comment)

feed_service = FeedGenerationService()
user_feed = feed_service.generate_feed(user_id)

User Interface: The front-end layer responsible for rendering the Agoda website or mobile app and providing an intuitive user experience.

Application Servers: The middle-tier servers that handle business logic, process user requests, and communicate with other system components.

Database: The backend storage layer where user data, property information, bookings, reviews, and other relevant data are stored.

External Services: Integration with external services like payment gateways, geolocation APIs, and third-party accommodation providers.

Caching Layer: A cache system to store frequently accessed data and improve performance.

Basic Low Level Design

class User:
    def __init__(self, user_id, username, password):
        self.user_id = user_id
        self.username = username
        self.password = password
        # Other user attributes

class Property:
    def __init__(self, property_id, name, location, price, amenities):
        self.property_id = property_id
        self.name = name
        self.location = location
        self.price = price
        self.amenities = amenities
        # Other property attributes

class Booking:
    def __init__(self, booking_id, user_id, property_id, check_in_date, check_out_date, guests):
        self.booking_id = booking_id
        self.user_id = user_id
        self.property_id = property_id
        self.check_in_date = check_in_date
        self.check_out_date = check_out_date
        self.guests = guests
        # Other booking attributes

class Review:
    def __init__(self, review_id, property_id, user_id, rating, comment):
        self.review_id = review_id
        self.property_id = property_id
        self.user_id = user_id
        self.rating = rating
        self.comment = comment
        # Other review attributes

class Agoda:
    def __init__(self):
        self.users = {}
        self.properties = {}
        self.bookings = {}
        self.reviews = {}
        # Initialize other data structures

    def add_user(self, user):
        self.users[user.user_id] = user

    def get_user_by_id(self, user_id):
        return self.users.get(user_id)

    def add_property(self, property):
        self.properties[property.property_id] = property

    def get_property_by_id(self, property_id):
        return self.properties.get(property_id)

    def create_booking(self, booking):
        self.bookings[booking.booking_id] = booking

    def create_review(self, review):
        self.reviews[review.review_id] = review

    # Additional methods for handling other operations

API Design

User Registration API:

  • Endpoint: /api/users/register
  • Method: POST
  • Description: Allows users to register a new account on Agoda.
  • Request Body:
  • { "name": "John Doe", "email": "[email protected]", "password": "password123" }
  • Success (200 OK):
  • { "message": "User registered successfully.", "user_id": "123456789" }
  • Error (4xx/5xx):
  • { "error": "Invalid request. Please provide valid user details." }

Property Search API:

  • Endpoint: /api/properties/search
  • Method: GET
  • Description: Retrieves a list of properties based on search criteria.
  • Query Parameters:
  • location (required): Location of the desired property.
  • check_in (required): Check-in date in YYYY-MM-DD format.
  • check_out (required): Check-out date in YYYY-MM-DD format.
  • guests (optional): Number of guests.
  • Response:
  • Success (200 OK):
  • { "properties": [ { "property_id": "abcd1234", "name": "Agoda Hotel", "location": "City X", "price": 100, "rating": 4.5 }, { "property_id": "efgh5678", "name": "Agoda Resort", "location": "Beach Y", "price": 200, "rating": 4.8 } ] }
  • Error (4xx/5xx):
  • { "error": "Invalid request. Please provide valid search criteria." }

Booking Creation API:

  • Endpoint: /api/bookings/create
  • Method: POST
  • Description: Creates a new booking for a specific property.
  • Request Body:
  • { "user_id": "123456789", "property_id": "abcd1234", "check_in": "2023-07-10", "check_out": "2023-07-15", "guests": 2 }
  • Response:
  • Success (200 OK):
  • { "message": "Booking created successfully.", "booking_id": "xyz987654" }
  • Error (4xx/5xx):
  • { "error": "Invalid request. Please provide valid booking details." }
from flask import Flask, request, jsonify

app = Flask(__name__)

# User Registration API
@app.route('/api/users/register', methods=['POST'])
def register_user():
    user_data = request.get_json()
    
    # Perform validation and user registration logic
    # ...

    return jsonify({
        "message": "User registered successfully.",
        "user_id": "123456789"
    }), 200

# Property Search API
@app.route('/api/properties/search', methods=['GET'])
def search_properties():
    location = request.args.get('location')
    check_in = request.args.get('check_in')
    check_out = request.args.get('check_out')
    guests = request.args.get('guests')

    # Perform property search logic
    # ...

    properties = [
        {
            "property_id": "abcd1234",
            "name": "Agoda Hotel",
            "location": "City X",
            "price": 100,
            "rating": 4.5
        },
        {
            "property_id": "efgh5678",
            "name": "Agoda Resort",
            "location": "Beach Y",
            "price": 200,
            "rating": 4.8
        }
    ]

    return jsonify({"properties": properties}), 200

# Booking Creation API
@app.route('/api/bookings/create', methods=['POST'])
def create_booking():
    booking_data = request.get_json()

    # Perform validation and booking creation logic
    # ...

    return jsonify({
        "message": "Booking created successfully.",
        "booking_id": "xyz987654"
    }), 200

# Run the Flask application
if __name__ == '__main__':
    app.run()

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

Search and Filtering:

def search_accommodations(location, price_range, amenities, user_ratings):
    # Perform search and filtering logic based on the provided parameters
    filtered_accommodations = []
    for accommodation in accommodations:
        if accommodation.location == location and \
           accommodation.price in price_range and \
           all(amenity in accommodation.amenities for amenity in amenities) and \
           accommodation.rating >= user_ratings:
            filtered_accommodations.append(accommodation)
    return filtered_accommodations

User Profiles and Personalization:

class User:
    def __init__(self, user_id, name, email):
        self.user_id = user_id
        self.name = name
        self.email = email
        self.favorite_properties = []
    def add_favorite_property(self, property_id):
        self.favorite_properties.append(property_id)
    def get_personalized_recommendations(self):
        # Perform personalized recommendation logic based on user's browsing and booking history
        recommended_properties = []
        # Logic to determine recommended properties based on user's history
        return recommended_properties

Booking and Payment:

class Booking:
    def __init__(self, booking_id, user_id, property_id, check_in, check_out, guests):
        self.booking_id = booking_id
        self.user_id = user_id
        self.property_id = property_id
        self.check_in = check_in
        self.check_out = check_out
        self.guests = guests
    def make_payment(self, payment_method):
        # Perform payment processing logic using the provided payment method
        # Logic to process payment
        return "Payment successful"

Reviews and Ratings:

class Review:
    def __init__(self, property_id, user_id, rating, comment):
        self.property_id = property_id
        self.user_id = user_id
        self.rating = rating
        self.comment = comment
    def submit_review(self):
        # Perform review submission logic
        # Logic to submit a review
        return "Review submitted successfully"
    @staticmethod
    def get_reviews(property_id):
        # Retrieve the reviews for the specified property
        property_reviews = []
        # Logic to retrieve reviews for the property
        return property_reviews

Multi-Language and Multi-Currency Support:

class Agoda:
    def __init__(self, language, currency):
        self.language = language
        self.currency = currency
    def set_language(self, language):
        self.language = language
    def set_currency(self, currency):
        self.currency = currency
    def convert_currency(self, amount, target_currency):
        # Perform currency conversion logic using exchange rates
        converted_amount = 0.0
        # Logic to convert amount to the target currency
        return converted_amount

User Management API:

  • POST /users: Creates a new user account.
  • GET /users/{user_id}: Retrieves user information by user ID.
  • PATCH /users/{user_id}: Updates user information.
  • DELETE /users/{user_id}: Deletes a user account.

Property Management API:

  • POST /properties: Adds a new property.
  • GET /properties/{property_id}: Retrieves property information by property ID.
  • PATCH /properties/{property_id}: Updates property information.
  • DELETE /properties/{property_id}: Deletes a property.

Booking API:

  • POST /bookings: Creates a new booking.
  • GET /bookings/{booking_id}: Retrieves booking information by booking ID.
  • PATCH /bookings/{booking_id}: Updates booking information.
  • DELETE /bookings/{booking_id}: Cancels a booking.

Review API:

  • POST /reviews: Creates a new review.
  • GET /reviews/{review_id}: Retrieves review information by review ID.
  • PATCH /reviews/{review_id}: Updates review information.
  • DELETE /reviews/{review_id}: Deletes a review.
from flask import Flask, request

app = Flask(__name__)
agoda = Agoda()

# User Management API
@app.route('/users', methods=['POST'])
def create_user():
    data = request.get_json()
    user = User(data['user_id'], data['username'], data['password'])
    agoda.add_user(user)
    return {'message': 'User created successfully'}, 201

@app.route('/users/<user_id>', methods=['GET'])
def get_user(user_id):
    user = agoda.get_user_by_id(user_id)
    if user:
        return {
            'user_id': user.user_id,
            'username': user.username,
            # Include other user attributes as needed
        }, 200
    else:
        return {'message': 'User not found'}, 404

# Property Management API
@app.route('/properties', methods=['POST'])
def create_property():
    data = request.get_json()
    property = Property(data['property_id'], data['name'], data['location'], data['price'], data['amenities'])
    agoda.add_property(property)
    return {'message': 'Property added successfully'}, 201

@app.route('/properties/<property_id>', methods=['GET'])
def get_property(property_id):
    property = agoda.get_property_by_id(property_id)
    if property:
        return {
            'property_id': property.property_id,
            'name': property.name,
            # Include other property attributes as needed
        }, 200
    else:
        return {'message': 'Property not found'}, 404

# Booking API
@app.route('/bookings', methods=['POST'])
def create_booking():
    data = request.get_json()
    booking = Booking(data['booking_id'], data['user_id'], data['property_id'], data['check_in_date'], data['check_out_date'], data['guests'])
    agoda.create_booking(booking)
    return {'message': 'Booking created successfully'}, 201

# Review API
@app.route('/reviews', methods=['POST'])
def create_review():
    data = request.get_json()
    review = Review(data['review_id'], data['property_id'], data['user_id'], data['rating'], data['comment'])
    agoda.create_review(review)
    return {'message': 'Review created successfully'}, 201

if __name__ == '__main__':
    app.run()

System Design — Razorpay

We will be discussing in depth -

Pic credits : Pinterest

What is Razorpay

Razorpay is a robust and user-friendly online payment gateway that enables businesses to accept and process digital payments securely. With a mission to simplify online transactions, Razorpay provides a wide range of payment solutions, including payment links, subscriptions, UPI (Unified Payments Interface), wallet options, and more.

Important Features

  1. Payment Gateway: Razorpay offers a reliable and secure payment gateway that allows businesses to accept payments from multiple sources, such as credit cards, debit cards, net banking, UPI, and popular digital wallets.
  2. Payment Links: This feature allows businesses to generate customized payment links and share them with customers via various channels like email, SMS, or social media. Customers can click on these links to make payments conveniently.
  3. Subscription Billing: Razorpay supports subscription-based billing models, enabling businesses to set up recurring payments for services or products. It provides automated billing cycles, trial periods, and subscription management capabilities.
  4. Smart Routing: Razorpay’s smart routing algorithm automatically directs transactions to the most reliable payment gateway based on factors like success rates, currency, and payment mode. This ensures high transaction success rates and better customer experience.
  5. Payment Reconciliation: Razorpay provides detailed transaction reports, settlement summaries, and reconciliation tools to simplify the accounting process for businesses. This feature helps in tracking and managing payment-related data efficiently.
  6. Developer-friendly APIs: Razorpay offers robust APIs and SDKs (Software Development Kits) that allow seamless integration with various platforms, including websites, mobile applications, and e-commerce platforms. It provides extensive documentation and developer support to ensure a smooth integration process.

Scaling Requirements — Capacity Estimation

For the sake of simplicity, let’s consider a smaller scale simulation for Razorpay:

Total number of users: 10 million

Daily active users (DAU): 2 million

Number of transactions per user per day: 2

Total number of transactions per day: 4 million transactions/day

Since the system is read-heavy, let’s assume the read-to-write ratio to be 100:1

Total number of transactions recorded per day: 4 million / 100 = 40,000 transactions/day

Storage Estimation:

Let’s assume each transaction record is approximately 1 KB in size.

Total storage per day: 40,000 transactions/day * 1 KB = 40 MB/day

For the next 3 years, 40 MB * 365 days * 3 years = 43.8 GB

Requests per second: 4 million transactions / (24 hours * 3600 seconds) = 46 requests/second

  1. Horizontal Scalability: The system should be able to handle increased transaction loads by adding more servers or instances. This allows for better distribution of workload and ensures high availability during peak periods.
  2. Caching Mechanism: Implementing an efficient caching mechanism reduces the load on the database by storing frequently accessed data in memory. This improves response times and overall system performance.
  3. Distributed Load Balancing: To distribute incoming traffic evenly across multiple servers, a load balancer is used. This helps in preventing overloading of any specific server and ensures optimal resource utilization.
  4. Database Sharding: To manage the growing volume of transaction data, the system can employ database sharding. Sharding involves partitioning the database across multiple servers to distribute the data load and improve query performance.

Data Model — ER requirements

Users:

  • Fields:
  • User ID: Integer (Primary Key)
  • Username: String
  • Email: String
  • Password: String

Transactions:

  • Fields:
  • Transaction ID: Integer (Primary Key)
  • User ID: Integer (Foreign Key referencing Users)
  • Amount: Decimal
  • Currency: String
  • Timestamp: DateTime

Payment Methods:

  • Fields:
  • Payment Method ID: Integer (Primary Key)
  • User ID: Integer (Foreign Key referencing Users)
  • Method Type: String
  • Card Number: String
  • Expiry Date: String

High Level Design

Assumptions:

  • Razorpay needs to handle a high volume of transactions.
  • The system should be designed to handle high availability and reliability.
  • The system should have low latency for payment processing.

Main Components :

  1. Mobile Clients: These are the users accessing the Razorpay system through mobile applications.
  2. Application Servers: These servers handle the processing of payment requests, user authentication, and other business logic.
  3. Load Balancer: The load balancer routes and distributes incoming requests across multiple application servers to ensure efficient utilization of resources and high availability.
  4. Cache (Memcache): The caching system improves performance by storing frequently accessed data in memory, such as user details and payment method information.
  5. CDN (Content Delivery Network): The CDN improves the delivery of static assets and reduces latency by caching and serving them from edge servers located closer to the users.
  6. Database: The database stores the user information, transaction records, and payment method details.
  7. Storage (HDFS or Amazon S3): The storage system is used to store additional data, such as transaction logs and backup files.

Services:

  1. Payment Service: This service handles payment processing, including authorization, capturing payments, and refunding payments.
  2. User Service: The user service manages user registration, authentication, and profile management.
  3. Transaction Service: The transaction service handles the creation and retrieval of transaction records, as well as transaction history.
  4. Payment Method Service: This service manages payment methods associated with user accounts, allowing users to add, update, or remove payment methods.
  5. Analytics Service: The analytics service collects and analyzes transaction data to provide insights, fraud detection, and reporting features.
  6. Notification Service: The notification service sends email or push notifications to users for transaction updates, payment reminders, or other relevant information.
from datetime import datetime

class RazorpayPaymentService:
    def __init__(self):
        # Initialize payment service configuration
        self.payment_gateway = "Razorpay"
    
    def process_payment(self, user_id, amount, currency):
        # Logic to process payment using Razorpay payment gateway
        # Implementation details omitted
        transaction_id = self.generate_transaction_id()
        timestamp = datetime.now()
        # Perform necessary operations to process the payment
        print(f"Payment processed for user {user_id}. Transaction ID: {transaction_id}. Amount: {amount} {currency}.")
        return transaction_id
    
    def generate_transaction_id(self):
        # Logic to generate a unique transaction ID
        # Implementation details omitted
        # Generate a unique transaction ID based on timestamp or other criteria
        return "TXN123456789"  # Placeholder value

class RazorpayUserService:
    def __init__(self):
        # Initialize user service configuration
        pass
    
    def register_user(self, username, email, password):
        # Logic to register a new user
        # Implementation details omitted
        # Perform necessary operations to register the user
        print(f"New user registered: {username} ({email})")
    
    def authenticate_user(self, email, password):
        # Logic to authenticate a user
        # Implementation details omitted
        # Perform necessary operations to authenticate the user
        user_id = self.get_user_id_by_email(email)
        if user_id:
            print(f"User {user_id} authenticated successfully.")
        else:
            print("Invalid credentials.")
    
    def get_user_id_by_email(self, email):
        # Logic to retrieve user ID by email
        # Implementation details omitted
        # Retrieve user ID based on the provided email
        return "user123"  # Placeholder value

class RazorpayTransactionService:
    def __init__(self):
        # Initialize transaction service configuration
        pass
    
    def get_transaction_details(self, transaction_id):
        # Logic to retrieve transaction details
        # Implementation details omitted
        # Retrieve transaction details based on the provided transaction ID
        transaction_details = {
            "transaction_id": transaction_id,
            "amount": 1000,
            "currency": "INR",
            "timestamp": datetime.now()
        }
        return transaction_details
    
    def get_transaction_history(self, user_id):
        # Logic to retrieve transaction history for a user
        # Implementation details omitted
        # Retrieve transaction history based on the provided user ID
        transaction_history = [
            {"transaction_id": "TXN123", "amount": 500, "currency": "INR", "timestamp": datetime.now()},
            {"transaction_id": "TXN456", "amount": 750, "currency": "USD", "timestamp": datetime.now()}
        ]
        return transaction_history

class RazorpayPaymentMethodService:
    def __init__(self):
        # Initialize payment method service configuration
        pass
    
    def add_payment_method(self, user_id, method_type, card_number, expiry_date):
        # Logic to add a payment method for a user
        # Implementation details omitted
        # Perform necessary operations to add the payment method
        print(f"Payment method added for user {user_id}. Method Type: {method_type}. Card Number: {card_number}.")
    
    def update_payment_method(self, user_id, method_type, card_number, expiry_date):
        # Logic to update a payment method for a user
        # Implementation details omitted
        # Perform necessary operations to update the payment method
        print(f"Payment method updated for user {user_id}. Method Type: {method_type}. Card Number: {card_number}.")
    
    def remove_payment_method(self, user_id, method_type, card_number):
        # Logic to remove a payment method for a user
        # Implementation details omitted
        # Perform necessary operations to remove the payment method
        print(f"Payment method removed for user {user_id}. Method Type: {method_type}. Card Number: {card_number}.")

class RazorpayAnalyticsService:
    def __init__(self):
        # Initialize analytics service configuration
        pass
    
    def analyze_transactions(self, transaction_history):
        # Logic to analyze transaction data
        # Implementation details omitted
        # Perform necessary operations to analyze transaction history and provide insights
        print("Analyzing transaction data...")
        # Placeholder logic: Print transaction details
        for transaction in transaction_history:
            print(f"Transaction ID: {transaction['transaction_id']}, Amount: {transaction['amount']} {transaction['currency']}")
    
    def detect_fraudulent_transactions(self, transaction_history):
        # Logic to detect fraudulent transactions
        # Implementation details omitted
        # Perform necessary operations to detect fraudulent transactions in the transaction history
        print("Detecting fraudulent transactions...")
        # Placeholder logic: Print transaction details
        for transaction in transaction_history:
            print(f"Transaction ID: {transaction['transaction_id']}, Amount: {transaction['amount']} {transaction['currency']}")

class RazorpayNotificationService:
    def __init__(self):
        # Initialize notification service configuration
        pass
    
    def send_notification(self, user_id, message):
        # Logic to send a notification to a user
        # Implementation details omitted
        # Perform necessary operations to send the notification
        print(f"Notification sent to user {user_id}: {message}")

# Example usage:

# Payment Service
payment_service = RazorpayPaymentService()
transaction_id = payment_service.process_payment(user_id="user123", amount=1000, currency="INR")
transaction_details = payment_service.get_transaction_details(transaction_id)
print("Transaction Details:", transaction_details)

# User Service
user_service = RazorpayUserService()
user_service.register_user(username="JohnDoe", email="[email protected]", password="password123")
user_service.authenticate_user(email="[email protected]", password="password123")

# Transaction Service
transaction_service = RazorpayTransactionService()
transaction_history = transaction_service.get_transaction_history(user_id="user123")
print("Transaction History:")
for transaction in transaction_history:
    print(transaction)

# Payment Method Service
payment_method_service = RazorpayPaymentMethodService()
payment_method_service.add_payment_method(user_id="user123", method_type="Credit Card", card_number="**** **** **** 1234", expiry_date="12/24")
payment_method_service.update_payment_method(user_id="user123", method_type="Credit Card", card_number="**** **** **** 5678", expiry_date="06/26")
payment_method_service.remove_payment_method(user_id="user123", method_type="Credit Card", card_number="**** **** **** 1234")

# Analytics Service
analytics_service = RazorpayAnalyticsService()
analytics_service.analyze_transactions(transaction_history)
analytics_service.detect_fraudulent_transactions(transaction_history)

# Notification Service
notification_service = RazorpayNotificationService()
notification_service.send_notification(user_id="user123", message="Payment received successfully!")
  1. Frontend Interface: The frontend interface handles user interactions and provides a seamless payment experience. It integrates with Razorpay’s APIs for processing transactions.
  2. API Gateway: Acts as the entry point for external requests and forwards them to the appropriate microservices within the system. It provides authentication, rate limiting, and request/response handling.
  3. Payment Processing: This component handles payment validation, authorization, and settlement processes. It interacts with external payment gateways, banks, and financial institutions to process the transactions securely.
  4. Database: Stores transactional data, user information, and other related entities. It should be scalable, highly available, and capable of handling high write and read loads.
  5. Analytics & Reporting: This component collects and analyzes transaction data to provide insights, generate reports, and facilitate reconciliation processes.

Basic Low Level Design

class User:
    def __init__(self, user_id, username, password):
        self.user_id = user_id
        self.username = username
        self.password = password
        # Other user attributes
    
class Transaction:
    def __init__(self, transaction_id, user, amount, currency):
        self.transaction_id = transaction_id
        self.user = user
        self.amount = amount
        self.currency = currency
        # Other transaction attributes
    
class Razorpay:
    def __init__(self):
        self.users = {}
        self.transactions = []
        
    def add_user(self, user):
        self.users[user.user_id] = user
        
    def get_user_by_id(self, user_id):
        return self.users.get(user_id)
        
    def create_transaction(self, user_id, amount, currency):
        user = self.get_user_by_id(user_id)
        if user:
            transaction_id = generate_transaction_id()
            transaction = Transaction(transaction_id, user, amount, currency)
            self.transactions.append(transaction)
            # Additional logic to process the transaction
        else:
            print("User not found.")
            
    def generate_transaction_id(self):
        # Logic to generate a unique transaction ID
        pass

API Design

import requests

class RazorpayAPI:
    def __init__(self, api_key, api_secret):
        self.api_key = api_key
        self.api_secret = api_secret

    def create_payment(self, amount, currency, method, customer_details):
        url = "https://api.razorpay.com/v1/payments"
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Basic {self.api_key}:{self.api_secret}"
        }
        data = {
            "amount": amount,
            "currency": currency,
            "method": method,
            "customer_details": customer_details
        }
        response = requests.post(url, json=data, headers=headers)
        if response.status_code == 200:
            payment_id = response.json().get("id")
            return payment_id
        else:
            raise Exception("Failed to create payment")

    def fetch_payment_details(self, payment_id):
        url = f"https://api.razorpay.com/v1/payments/{payment_id}"
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Basic {self.api_key}:{self.api_secret}"
        }
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            payment_details = response.json()
            return payment_details
        else:
            raise Exception("Failed to fetch payment details")

    def capture_payment(self, payment_id, amount):
        url = f"https://api.razorpay.com/v1/payments/{payment_id}/capture"
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Basic {self.api_key}:{self.api_secret}"
        }
        data = {
            "amount": amount
        }
        response = requests.post(url, json=data, headers=headers)
        if response.status_code == 200:
            payment_status = response.json().get("status")
            return payment_status
        else:
            raise Exception("Failed to capture payment")

    def refund_payment(self, payment_id, amount):
        url = f"https://api.razorpay.com/v1/payments/{payment_id}/refund"
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Basic {self.api_key}:{self.api_secret}"
        }
        data = {
            "amount": amount
        }
        response = requests.post(url, json=data, headers=headers)
        if response.status_code == 200:
            refund_status = response.json().get("status")
            return refund_status
        else:
            raise Exception("Failed to refund payment")

# Example Usage
razorpay_api = RazorpayAPI("<your_api_key>", "<your_api_secret>")

# Create Payment
payment_id = razorpay_api.create_payment(1000, "INR", "card", {"name": "John Doe", "email": "[email protected]"})

# Fetch Payment Details
payment_details = razorpay_api.fetch_payment_details(payment_id)

# Capture Payment
capture_status = razorpay_api.capture_payment(payment_id, 1000)

# Refund Payment
refund_status = razorpay_api.refund_payment(payment_id, 500)
  1. Create Payment: This endpoint allows merchants to initiate a payment transaction. It requires parameters such as the amount, currency, payment method, and customer details. Upon successful creation, it returns a unique payment ID.
  2. Fetch Payment Details: Merchants can use this endpoint to retrieve the details of a specific payment using its payment ID. It returns information such as the payment status, amount, customer details, and payment method.
  3. Webhook Notification: Razorpay sends webhook notifications to the merchant’s server for important events, such as successful payment, failed payment, or refund. The merchant needs to configure a webhook URL to receive these notifications.
  4. Capture Payment: This endpoint is used to capture an authorized but uncaptured payment. It requires the payment ID and the amount to be captured. On successful capture, the payment status is updated accordingly.
  5. Refund Payment: Merchants can initiate a refund for a payment using this endpoint. It requires the payment ID and the refund amount. The refund status and details are returned upon successful refund.
  6. Subscription Management: This set of endpoints enables merchants to manage subscription-based billing. It includes endpoints for creating subscriptions, fetching subscription details, updating subscriptions, and canceling subscriptions.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class Payment(BaseModel):
    amount: float
    currency: str
    method: str
    customer_details: dict

@app.post("/payments")
def create_payment(payment: Payment):
    # Code to create a payment in Razorpay
    payment_id = create_payment_in_razorpay(payment.amount, payment.currency, payment.method, payment.customer_details)
    
    if payment_id:
        return {"payment_id": payment_id}
    else:
        raise HTTPException(status_code=500, detail="Failed to create payment")

@app.get("/payments/{payment_id}")
def get_payment(payment_id: str):
    # Code to fetch payment details from Razorpay
    payment_details = fetch_payment_details_from_razorpay(payment_id)
    
    if payment_details:
        return payment_details
    else:
        raise HTTPException(status_code=404, detail="Payment not found")

@app.post("/payments/{payment_id}/capture")
def capture_payment(payment_id: str, amount: float):
    # Code to capture a payment in Razorpay
    capture_status = capture_payment_in_razorpay(payment_id, amount)
    
    if capture_status:
        return {"status": capture_status}
    else:
        raise HTTPException(status_code=500, detail="Failed to capture payment")

@app.post("/payments/{payment_id}/refund")
def refund_payment(payment_id: str, amount: float):
    # Code to refund a payment in Razorpay
    refund_status = refund_payment_in_razorpay(payment_id, amount)
    
    if refund_status:
        return {"status": refund_status}
    else:
        raise HTTPException(status_code=500, detail="Failed to refund payment")

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

class RazorpayPaymentGateway:
    def __init__(self):
        # Initialize payment gateway configuration
        self.payment_gateway = "Razorpay"
    
    def accept_payment(self, payment_details):
        # Logic to accept payments using Razorpay payment gateway
        # Implementation details omitted
        # Perform necessary operations to accept payment
        print(f"Payment of {payment_details['amount']} {payment_details['currency']} accepted using Razorpay")
    
    def generate_payment_link(self, amount, currency, customer_email):
        # Logic to generate payment link using Razorpay
        # Implementation details omitted
        payment_link = f"https://razorpay.com/payment-link/{customer_email}?amount={amount}&currency={currency}"
        return payment_link
    
class RazorpaySubscription:
    def __init__(self):
        # Initialize subscription billing configuration
        self.billing_system = "Razorpay"
    
    def create_subscription(self, customer_id, plan_id, start_date, trial_days):
        # Logic to create a subscription using Razorpay
        # Implementation details omitted
        # Perform necessary operations to create a subscription
        print(f"Subscription created for customer {customer_id} with plan {plan_id} starting on {start_date} with {trial_days} days trial")
    
    def update_subscription(self, subscription_id, new_plan_id):
        # Logic to update a subscription using Razorpay
        # Implementation details omitted
        # Perform necessary operations to update the subscription
        print(f"Subscription {subscription_id} updated with new plan {new_plan_id}")

class RazorpaySmartRouting:
    def __init__(self):
        # Initialize smart routing configuration
        self.smart_routing_enabled = True
    
    def route_transaction(self, transaction_details):
        # Logic to route a transaction using Razorpay's smart routing algorithm
        # Implementation details omitted
        # Perform necessary operations to route the transaction
        print("Transaction routed using Razorpay's smart routing")

class RazorpayPaymentReconciliation:
    def __init__(self):
        # Initialize payment reconciliation configuration
        self.reconciliation_enabled = True
    
    def generate_transaction_report(self, start_date, end_date):
        # Logic to generate transaction report using Razorpay
        # Implementation details omitted
        # Perform necessary operations to generate the transaction report
        print(f"Transaction report generated for the period {start_date} to {end_date}")

class RazorpayAPI:
    def __init__(self):
        # Initialize API configuration
        self.api_key = "your_api_key"
        self.api_secret = "your_api_secret"
    
    def integrate_with_website(self):
        # Logic to integrate Razorpay API with website
        # Implementation details omitted
        # Perform necessary operations to integrate with the website
        print("Integrated Razorpay API with website")
    
    def integrate_with_mobile_app(self):
        # Logic to integrate Razorpay API with mobile app
        # Implementation details omitted
        # Perform necessary operations to integrate with the mobile app
        print("Integrated Razorpay API with mobile app")
    
    def integrate_with_ecommerce_platform(self):
        # Logic to integrate Razorpay API with ecommerce platform
        # Implementation details omitted
        # Perform necessary operations to integrate with the ecommerce platform
        print("Integrated Razorpay API with ecommerce platform")

# Example usage:

# Payment Gateway
payment_gateway = RazorpayPaymentGateway()
payment_details = {
    "amount": 1000,
    "currency": "INR",
    "customer_email": "[email protected]"
}
payment_gateway.accept_payment(payment_details)

# Payment Links
payment_link_generator = RazorpayPaymentGateway()
amount = 500
currency = "USD"
customer_email = "[email protected]"
payment_link = payment_link_generator.generate_payment_link(amount, currency, customer_email)
print("Payment Link:", payment_link)

# Subscription Billing
subscription_manager = RazorpaySubscription()
customer_id = "customer_123"
plan_id = "plan_456"
start_date = "2023-07-01"
trial_days = 7
subscription_manager.create_subscription(customer_id, plan_id, start_date, trial_days)

# Smart Routing
smart_router = RazorpaySmartRouting()
transaction_details = {
    "amount": 2000,
    "currency": "INR",
    "success_rate": 0.85
}
smart_router.route_transaction(transaction_details)

# Payment Reconciliation
payment_reconciler = RazorpayPaymentReconciliation()
start_date = "2023-06-01"
end_date = "2023-06-30"
payment_reconciler.generate_transaction_report(start_date, end_date)

# Developer-friendly APIs
razorpay_api = RazorpayAPI()
razorpay_api.integrate_with_website()
razorpay_api.integrate_with_mobile_app()
razorpay_api.integrate_with_ecommerce_platform()
from flask import Flask, request, jsonify

app = Flask(__name__)

razorpay = Razorpay()  # Assuming the Razorpay class is already defined

@app.route("/users", methods=["POST"])
def register_user():
    data = request.get_json()
    user_id = data["user_id"]
    username = data["username"]
    password = data["password"]
    user = User(user_id, username, password)
    razorpay.add_user(user)
    return jsonify({"message": "User registered successfully"}), 200

@app.route("/login", methods=["POST"])
def authenticate_user():
    data = request.get_json()
    username = data["username"]
    password = data["password"]
    user = razorpay.authenticate_user(username, password)
    if user:
        return jsonify({"message": "Authentication successful"}), 200
    else:
        return jsonify({"message": "Authentication failed"}), 401

@app.route("/users/<user_id>/transactions", methods=["POST"])
def create_transaction(user_id):
    data = request.get_json()
    amount = data["amount"]
    currency = data["currency"]
    razorpay.create_transaction(user_id, amount, currency)
    return jsonify({"message": "Transaction created successfully"}), 200

@app.route("/users/<user_id>/transactions", methods=["GET"])
def get_transaction_history(user_id):
    transaction_history = razorpay.get_transaction_history(user_id)
    return jsonify(transaction_history), 200

@app.route("/users/<user_id>", methods=["GET"])
def get_user(user_id):
    user = razorpay.get_user_by_id(user_id)
    if user:
        return jsonify(user.__dict__), 200
    else:
        return jsonify({"message": "User not found"}), 404

@app.route("/users/<user_id>/transactions/<transaction_id>", methods=["GET"])
def get_transaction(user_id, transaction_id):
    transaction = razorpay.get_transaction(user_id, transaction_id)
    if transaction:
        return jsonify(transaction.__dict__), 200
    else:
        return jsonify({"message": "Transaction not found"}), 404

if __name__ == "__main__":
    app.run()

System Design — Apple Music

We will be discussing in depth -

What is Apple Music

Apple Music is a popular music streaming service offered by Apple Inc. It allows users to stream and download a vast collection of music from various genres and artists. With a seamless integration across Apple devices, Apple Music provides a personalized and immersive music experience for millions of users worldwide.

Important Features

  • Music Library: Apple Music offers a comprehensive music library with millions of songs, albums, playlists, and music videos. Users can discover new music, create playlists, and access their favorite songs on-demand.
  • Personalized Recommendations: The platform utilizes advanced algorithms and machine learning techniques to provide personalized recommendations based on users’ listening history, preferences, and curated playlists.
  • Radio Stations: Apple Music offers a wide range of radio stations curated by experts and renowned artists. Users can tune in to live radio shows, explore different genres, and discover new music.
  • Offline Listening: Users can download their favorite songs and playlists for offline listening, enabling uninterrupted music playback even without an internet connection.
  • Social Integration: Apple Music allows users to connect with friends, follow their favorite artists, and share their music preferences on social media platforms. It fosters a sense of community among music enthusiasts.

Scaling Requirements — Capacity Estimation

Let’s assume —

Total number of users: 500 million

Daily active users (DAU): 100 million

Number of songs listened to by a user per day: 5

Total number of songs listened to per day: 500 million

Assuming a read-heavy system with a read-to-write ratio of 100:1, we can estimate the number of songs uploaded per day:

Total number of songs uploaded per day = 1/100 * 500 million = 5 million

Storage Estimation:

Let’s assume an average song size of 5 MB.

Total Storage per day: 5 million * 5 MB = 25 TB/day

Over the next 3 years, the estimated storage requirement will be:

Total Storage over 3 years = 25 TB/day * 365 days * 3 years = 27.375 PB

Requests per Second:

To estimate the requests per second, we’ll consider the average number of songs streamed per second:

Requests per second = 500 million / (24 hours * 3600 seconds) = 5,787 songs/second

Load Balancing: Implementing load balancers to distribute incoming requests evenly across multiple servers to prevent overloading and ensure high availability.

Caching: Utilizing caching techniques to reduce the load on backend servers, improve response times, and enhance scalability.

Content Delivery Networks (CDNs): Leveraging CDNs to deliver music content efficiently by caching and distributing it across multiple geographic locations.

Horizontal Scaling: Scaling horizontally by adding more servers to the system to handle increased user traffic and provide optimal performance.

Database Sharding: Implementing database sharding to horizontally partition the database and distribute data across multiple nodes to improve read/write performance.

Data Model — ER requirements

User Entity:

  • Fields: User_id, Username, Email, Password
  • Relationships: Users can have multiple playlists, likes, and comments

Song Entity:

  • Fields: Song_id, Title, Artist, Album, Duration
  • Relationships: Songs can be part of multiple albums and playlists, can have multiple likes and comments

Album Entity:

  • Fields: Album_id, Title, Artist, Release_date
  • Relationships: Albums can contain multiple songs

Playlist Entity:

  • Fields: Playlist_id, Title
  • Relationships: Playlists can contain multiple songs and are associated with a specific user

Like Entity:

  • Fields: Like_id, User_id, Song_id
  • Relationships: Likes are associated with a user and a specific song

Comment Entity:

  • Fields: Comment_id, User_id, Song_id, Text, Timestamp
  • Relationships: Comments are associated with a user and a specific song

High Level Design

Assumptions:

  • Apple Music will have a large user base with millions of active users.
  • The system will primarily handle read operations for browsing and streaming music.
  • The system should provide high availability, low latency, and scalability.

Main Components and Services:

  1. Mobile Clients: These are the user-facing applications for accessing Apple Music on mobile devices, providing interfaces for browsing, searching, and streaming music.
  2. Application Servers: These servers handle the business logic and orchestrate the flow of data between clients, databases, and external services. They handle user authentication, playlist management, and content recommendation.
  3. Load Balancer: The load balancer distributes incoming requests from mobile clients to multiple application servers, ensuring even distribution of the workload and improving scalability and fault tolerance.
  4. Caching Layer: A caching layer, such as Memcached or Redis, can be utilized to cache frequently accessed data, reducing the load on databases and improving response times.
  5. Content Delivery Network (CDN): A CDN can be employed to cache and distribute music content, such as songs, albums, and playlists, across multiple geographic locations, improving the delivery speed and reducing latency.
  6. Database: The database stores the data related to users, songs, albums, playlists, likes, and comments. It should be scalable, highly available, and capable of handling a large volume of read operations.
  7. Storage: The storage component is responsible for storing the actual music files, such as songs and albums, in a reliable and scalable manner. It can leverage cloud-based storage services like Amazon S3 or a distributed file system like HDFS.
  8. Recommendation Engine: This service utilizes advanced algorithms and machine learning techniques to analyze user preferences, listening history, and behavior to provide personalized music recommendations.
  9. Authentication and Authorization: This service handles user authentication and authorization, ensuring secure access to user accounts and protecting sensitive information.
  10. Music Metadata Management: This service manages and stores metadata related to songs, albums, artists, and genres, enabling efficient search and retrieval of music content.
  11. Like and Comment Services: These services handle user interactions such as liking songs, albums, or playlists, as well as posting comments and managing replies.

Client Applications: Native mobile apps for iOS and Android, along with a web application, provide user interfaces for browsing, searching, and streaming music.

Authentication and Authorization: This component handles user authentication, authorization, and session management, ensuring secure access to user accounts.

Content Delivery System: The system utilizes CDNs for efficient content delivery, reducing latency and providing faster access to music files.

Recommendation Engine: Powered by machine learning algorithms, this component generates personalized music recommendations based on user preferences, listening history, and contextual data.

Metadata Management: This component manages and stores metadata related to songs, albums, artists, playlists, and genres. It ensures data consistency and availability.

User Interaction Management: This component handles user interactions, such as likes, dislikes, ratings, and comments, and stores them for future analysis and personalization.

Basic Low Level Design

from flask import Flask, request, jsonify

app = Flask(__name__)

# Data Storage
users = {}
songs = {}
playlists = {}
likes = {}
comments = {}

# User Class
class User:
    def __init__(self, user_id, username, password, email):
        self.user_id = user_id
        self.username = username
        self.password = password
        self.email = email
        self.playlists = []

# Song Class
class Song:
    def __init__(self, song_id, title, artist, album, duration):
        self.song_id = song_id
        self.title = title
        self.artist = artist
        self.album = album
        self.duration = duration
        self.likes = []
        self.comments = []

# Playlist Class
class Playlist:
    def __init__(self, playlist_id, title):
        self.playlist_id = playlist_id
        self.title = title
        self.songs = []

# User Management API - Create a new user account
@app.route('/users', methods=['POST'])
def create_user():
    data = request.get_json()
    user_id = len(users) + 1
    username = data.get('username')
    password = data.get('password')
    email = data.get('email')
    user = User(user_id, username, password, email)
    users[user_id] = user
    return jsonify(message="User created successfully"), 201

# Song Management API - Add a new song to the music library
@app.route('/songs', methods=['POST'])
def add_song():
    data = request.get_json()
    song_id = len(songs) + 1
    title = data.get('title')
    artist = data.get('artist')
    album = data.get('album')
    duration = data.get('duration')
    song = Song(song_id, title, artist, album, duration)
    songs[song_id] = song
    return jsonify(message="Song added successfully"), 201

# Playlist Management API - Create a new playlist for a specific user
@app.route('/users/<int:user_id>/playlists', methods=['POST'])
def create_playlist(user_id):
    data = request.get_json()
    playlist_id = len(playlists) + 1
    title = data.get('title')
    playlist = Playlist(playlist_id, title)
    user = users.get(user_id)
    if user:
        user.playlists.append(playlist)
        playlists[playlist_id] = playlist
        return jsonify(message="Playlist created successfully"), 201
    else:
        return jsonify(message="User not found"), 404

# Like API - Like a specific song for a user
@app.route('/users/<int:user_id>/likes', methods=['POST'])
def like_song(user_id):
    data = request.get_json()
    song_id = data.get('song_id')
    user = users.get(user_id)
    song = songs.get(song_id)
    if user and song:
        song.likes.append(user)
        likes[(user_id, song_id)] = True
        return jsonify(message="Song liked successfully"), 200
    else:
        return jsonify(message="User or song not found"), 404

# Comment API - Add a comment on a specific song for a user
@app.route('/users/<int:user_id>/comments', methods=['POST'])
def add_comment(user_id):
    data = request.get_json()
    song_id = data.get('song_id')
    text = data.get('text')
    user = users.get(user_id)
    song = songs.get(song_id)
    if user and song:
        comment_id = len(song.comments) + 1
        comment = {
            'comment_id': comment_id,
            'user_id': user_id,
            'song_id': song_id,
            'text': text
        }
        song.comments.append(comment)
        comments[comment_id] = comment
        return jsonify(message="Comment added successfully"), 200
    else:
        return jsonify(message="User or song not found"), 404

# Search API - Search for songs or albums based on a given query
@app.route('/search', methods=['GET'])
def search():
    query = request.args.get('q')
    search_results = []
    for song in songs.values():
        if query.lower() in song.title.lower() or query.lower() in song.album.lower() or query.lower() in song.artist.lower():
            search_results.append(song)
    return jsonify(songs=search_results)

# Playlist API - Get details of a specific playlist for a user
@app.route('/users/<int:user_id>/playlists/<int:playlist_id>', methods=['GET'])
def get_playlist(user_id, playlist_id):
    user = users.get(user_id)
    playlist = playlists.get(playlist_id)
    if user and playlist in user.playlists:
        return jsonify(playlist=playlist.__dict__), 200
    else:
        return jsonify(message="User or playlist not found"), 404

# User Feed API - Get the user's personalized feed with recommended songs and playlists
@app.route('/users/<int:user_id>/feed', methods=['GET'])
def get_feed(user_id):
    user = users.get(user_id)
    if user:
        feed = []
        for playlist in user.playlists:
            feed.extend(playlist.songs)
        return jsonify(feed=feed), 200
    else:
        return jsonify(message="User not found"), 404

if __name__ == '__main__':
    app.run(debug=True)

API Design

User Management API:

  • Endpoint: POST /users
  • Description: Create a new user account.
  • Request body: { “username”: “john123”, “password”: “password123”, “email”: “[email protected]” }

Song Management API:

  • Endpoint: POST /songs
  • Description: Add a new song to the music library.
  • Request body: { “title”: “Song Title”, “artist”: “Artist Name”, “album”: “Album Name”, “duration”: 240 }

Playlist Management API:

  • Endpoint: POST /users/{userId}/playlists
  • Description: Create a new playlist for a specific user.
  • Request body: { “title”: “My Playlist”, “songs”: [ “songId1”, “songId2” ] }

Like API:

  • Endpoint: POST /users/{userId}/likes
  • Description: Like a specific song for a user.
  • Request body: { “songId”: “songId1” }

Comment API:

  • Endpoint: POST /users/{userId}/comments
  • Description: Add a comment on a specific song for a user.
  • Request body: { “songId”: “songId1”, “text”: “Great song!” }

Search API:

  • Endpoint: GET /search?q={query}
  • Description: Search for songs or albums based on a given query.
  • Response: List of songs or albums matching the query.

Playlist API:

  • Endpoint: GET /users/{userId}/playlists/{playlistId}
  • Description: Get details of a specific playlist for a user.
  • Response: Playlist information with associated songs.

User Feed API:

  • Endpoint: GET /users/{userId}/feed
  • Description: Get the user’s personalized feed with recommended songs and playlists.
  • Response: User’s feed containing recommended songs and playlists.
from flask import Flask, request, jsonify

app = Flask(__name__)

# Data Storage
users = {}
songs = {}
playlists = {}
likes = {}
comments = {}

# User Class
class User:
    def __init__(self, user_id, username, password, email):
        self.user_id = user_id
        self.username = username
        self.password = password
        self.email = email
        self.playlists = []

# Song Class
class Song:
    def __init__(self, song_id, title, artist, album, duration):
        self.song_id = song_id
        self.title = title
        self.artist = artist
        self.album = album
        self.duration = duration
        self.likes = []
        self.comments = []

# Playlist Class
class Playlist:
    def __init__(self, playlist_id, title):
        self.playlist_id = playlist_id
        self.title = title
        self.songs = []

# User Management API - Create a new user account
@app.route('/users', methods=['POST'])
def create_user():
    data = request.get_json()
    user_id = len(users) + 1
    username = data.get('username')
    password = data.get('password')
    email = data.get('email')
    user = User(user_id, username, password, email)
    users[user_id] = user
    return jsonify(message="User created successfully"), 201

# Song Management API - Add a new song to the music library
@app.route('/songs', methods=['POST'])
def add_song():
    data = request.get_json()
    song_id = len(songs) + 1
    title = data.get('title')
    artist = data.get('artist')
    album = data.get('album')
    duration = data.get('duration')
    song = Song(song_id, title, artist, album, duration)
    songs[song_id] = song
    return jsonify(message="Song added successfully"), 201

# Playlist Management API - Create a new playlist for a specific user
@app.route('/users/<int:user_id>/playlists', methods=['POST'])
def create_playlist(user_id):
    data = request.get_json()
    playlist_id = len(playlists) + 1
    title = data.get('title')
    playlist = Playlist(playlist_id, title)
    user = users.get(user_id)
    if user:
        user.playlists.append(playlist)
        playlists[playlist_id] = playlist
        return jsonify(message="Playlist created successfully"), 201
    else:
        return jsonify(message="User not found"), 404

# Like API - Like a specific song for a user
@app.route('/users/<int:user_id>/likes', methods=['POST'])
def like_song(user_id):
    data = request.get_json()
    song_id = data.get('song_id')
    user = users.get(user_id)
    song = songs.get(song_id)
    if user and song:
        song.likes.append(user)
        likes[(user_id, song_id)] = True
        return jsonify(message="Song liked successfully"), 200
    else:
        return jsonify(message="User or song not found"), 404

# Comment API - Add a comment on a specific song for a user
@app.route('/users/<int:user_id>/comments', methods=['POST'])
def add_comment(user_id):
    data = request.get_json()
    song_id = data.get('song_id')
    text = data.get('text')
    user = users.get(user_id)
    song = songs.get(song_id)
    if user and song:
        comment_id = len(song.comments) + 1
        comment = {
            'comment_id': comment_id,
            'user_id': user_id,
            'song_id': song_id,
            'text': text
        }
        song.comments.append(comment)
        comments[comment_id] = comment
        return jsonify(message="Comment added successfully"), 200
    else:
        return jsonify(message="User or song not found"), 404

# Search API - Search for songs or albums based on a given query
@app.route('/search', methods=['GET'])
def search():
    query = request.args.get('q')
    search_results = []
    for song in songs.values():
        if query.lower() in song.title.lower() or query.lower() in song.album.lower() or query.lower() in song.artist.lower():
            search_results.append(song.__dict__)
    return jsonify(songs=search_results)

# Playlist API - Get details of a specific playlist for a user
@app.route('/users/<int:user_id>/playlists/<int:playlist_id>', methods=['GET'])
def get_playlist(user_id, playlist_id):
    user = users.get(user_id)
    playlist = playlists.get(playlist_id)
    if user and playlist in user.playlists:
        return jsonify(playlist=playlist.__dict__), 200
    else:
        return jsonify(message="User or playlist not found"), 404

# User Feed API - Get the user's personalized feed with recommended songs and playlists
@app.route('/users/<int:user_id>/feed', methods=['GET'])
def get_feed(user_id):
    user = users.get(user_id)
    if user:
        feed = []
        for playlist in user.playlists:
            feed.extend(playlist.songs)
        return jsonify(feed=feed), 200
    else:
        return jsonify(message="Usernot found"), 404

if __name__ == '__main__':
    app.run(debug=True)

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

System Design — CricHD

We will be discussing in depth -

Pic credits : Pinterest

What is CricHD

Crichd is an online platform designed to provide cricket enthusiasts with seamless access to live cricket matches and related content. With Crichd, users can watch matches in real-time, access match highlights, view player statistics, and engage with a vibrant cricket community. The platform supports a wide range of devices, including desktops, smartphones, and smart TVs.

Important Features

  • Live Streaming: Crichd enables users to watch live cricket matches from various leagues and tournaments.
  • Match Highlights: Users can catch up on the most exciting moments of a match through curated highlights.
  • Player Statistics: Crichd offers comprehensive player profiles and statistics, allowing fans to track their favorite players’ performance.
  • Commentary and Analysis: Users can access live commentary and post-match analysis to gain deeper insights into the game.
  • Social Interaction: Crichd facilitates user engagement through chat forums, polls, and social media integration.
  • Personalization: The platform provides personalized recommendations based on user preferences and viewing history.

Scaling Requirements — Capacity Estimation

Let’s assume —

Total number of users: 100 Million

Daily active users (DAU): 20 Million

Number of videos watched by user/day: 2

Total number of videos watched per day: 40 Million videos/day

Since the system is read-heavy, let’s assume the read-to-write ratio to be 100:1.

Total number of videos uploaded/day = 1/100 * 40 Million = 400,000 videos/day

Storage Estimation: Let’s assume the average size of each video is 100 MB.

Total Storage per day: 400,000 * 100 MB = 40 TB/day

For the next 3 years, the estimated storage will be: 40 TB * 365 days * 3 years = 43,800 TB = 43.8 PB

Requests per second: 40 Million / 3600 seconds * 24 hours = 11.1K/second

To ensure a smooth and responsive user experience, Crichd needs to handle a large number of concurrent users during peak times, such as major cricket tournaments. The system must be capable of scaling horizontally by adding more servers and load balancers to distribute the incoming traffic efficiently. Additionally, a robust content delivery network (CDN) should be employed to reduce latency and improve streaming performance across different geographical regions.

Data Model — ER requirements

Users:

  • Fields:
  • User_id: Int (Primary Key)
  • Username: String
  • Email: String
  • Password: String

Matches:

  • Fields:
  • Match_id: Int (Primary Key)
  • Team1: String
  • Team2: String
  • Venue: String
  • Date: Date
  • Status: String

Videos:

  • Fields:
  • Video_id: Int (Primary Key)
  • Match_id: Int (Foreign Key to Matches.Match_id)
  • Video_url: String
  • Caption: String
  • Timestamp: DateTime

Likes:

  • Fields:
  • Like_id: Int (Primary Key)
  • User_id: Int (Foreign Key to Users.User_id)
  • Video_id: Int (Foreign Key to Videos.Video_id)
  • Timestamp: DateTime

Comments:

  • Fields:
  • Comment_id: Int (Primary Key)
  • User_id: Int (Foreign Key to Users.User_id)
  • Video_id: Int (Foreign Key to Videos.Video_id)
  • Caption_text: String
  • Timestamp: DateTime

High Level Design

Assumptions:

  • There will be more reads than writes, so the system should be designed to handle read-heavy traffic.
  • Scalability is essential, and the system should be able to handle a large number of concurrent users.
  • Availability and reliability are crucial for providing a seamless streaming experience.
  • Latency should be minimized to ensure smooth video playback.

Main Components and Services:

Mobile/Web Clients:

  • These are the users accessing the Crichd streaming service through mobile or web applications.

Application Servers:

  • Responsible for handling read and write operations.
  • Serve requests from the clients, process business logic, and interact with the database.
  • Perform operations such as video streaming, likes, comments, and user authentication.

Load Balancer:

  • Routes and distributes incoming requests from clients to multiple application servers to ensure scalability and high availability.
  • Helps distribute the load evenly and handle traffic spikes effectively.

Cache (e.g., Memcache, Redis):

  • Used to cache frequently accessed data to improve performance and reduce load on the database.
  • Caches user profiles, video metadata, and other frequently requested data to minimize database queries.

Content Delivery Network (CDN):

  • Distributes video content to various geographical locations, reducing latency and improving streaming performance.
  • Caches video files at edge servers strategically placed near the users’ locations for faster content delivery.

Database:

  • Stores user data, match details, video metadata, likes, comments, and other relevant information.
  • Utilizes NoSQL databases (e.g., MongoDB, Cassandra) for flexibility and scalability.
  • Ensures high reliability and availability to maintain data integrity.

Services:

Video Streaming Service:

  • Handles the streaming of live cricket matches and recorded videos.
  • Retrieves video files from storage or CDN and delivers them to the clients for playback.
  • Supports adaptive streaming to adjust video quality based on the user’s network conditions.

Like Service:

  • Manages user likes for videos.
  • Provides the ability for users to like a specific video.
  • Stores the relationship between users and videos they have liked.

Comment Service:

  • Manages user comments on videos.
  • Enables users to post comments and replies on videos.
  • Stores the relationship between users, videos, and their associated comments.

User Authentication Service:

  • Handles user authentication and authorization.
  • Verifies user credentials and provides access tokens or sessions for authenticated users.
  • Ensures secure access to user-specific functionalities.

Recommendation Service:

  • Provides personalized recommendations to users based on their preferences and viewing history.
  • Utilizes machine learning algorithms to analyze user behavior and suggest relevant videos or matches.

Feed Generation Service:

  • Generates personalized feeds for users based on the videos they follow and interact with.
  • Aggregates video content, applies ranking algorithms, and presents a curated feed to each user.
  • Supports functionalities like displaying recent, popular, and relevant videos in the user’s feed.
from flask import Flask, jsonify, request

app = Flask(__name__)

# Sample data
users = {
    "user1": {"username": "John", "email": "[email protected]"},
    "user2": {"username": "Alice", "email": "[email protected]"}
}

matches = {
    "match1": {"team1": "Team A", "team2": "Team B", "venue": "Stadium X"},
    "match2": {"team1": "Team C", "team2": "Team D", "venue": "Stadium Y"}
}

# User API endpoints
@app.route("/users/<user_id>", methods=["GET"])
def get_user(user_id):
    if user_id in users:
        user = users[user_id]
        return jsonify(user), 200
    else:
        return jsonify({"message": "User not found"}), 404

@app.route("/users", methods=["POST"])
def create_user():
    data = request.get_json()
    user_id = data.get("user_id")
    username = data.get("username")
    email = data.get("email")
    user = {"username": username, "email": email}
    users[user_id] = user
    return jsonify({"message": "User created successfully"}), 201

# Match API endpoints
@app.route("/matches/<match_id>", methods=["GET"])
def get_match(match_id):
    if match_id in matches:
        match = matches[match_id]
        return jsonify(match), 200
    else:
        return jsonify({"message": "Match not found"}), 404

# Live Streaming Service
@app.route("/matches/<match_id>/stream", methods=["GET"])
def live_stream(match_id):
    if match_id in matches:
        # Code for live streaming logic
        return jsonify({"message": "Live streaming for match {} is available".format(match_id)}), 200
    else:
        return jsonify({"message": "Match not found"}), 404

# Match Highlights Service
@app.route("/matches/<match_id>/highlights", methods=["GET"])
def match_highlights(match_id):
    if match_id in matches:
        # Code for retrieving match highlights
        return jsonify({"message": "Match highlights for match {} are available".format(match_id)}), 200
    else:
        return jsonify({"message": "Match not found"}), 404

# Player Statistics Service
@app.route("/matches/<match_id>/players/<player_id>/stats", methods=["GET"])
def player_stats(match_id, player_id):
    if match_id in matches:
        # Code for retrieving player statistics
        return jsonify({"message": "Player statistics for player {} in match {} are available".format(player_id, match_id)}), 200
    else:
        return jsonify({"message": "Match not found"}), 404

# Commentary and Analysis Service
@app.route("/matches/<match_id>/commentary", methods=["GET"])
def commentary(match_id):
    if match_id in matches:
        # Code for retrieving live commentary and analysis
        return jsonify({"message": "Commentary and analysis for match {} are available".format(match_id)}), 200
    else:
        return jsonify({"message": "Match not found"}), 404

# Social Interaction Service
@app.route("/matches/<match_id>/interactions", methods=["POST"])
def social_interaction(match_id):
    if match_id in matches:
        data = request.get_json()
        interaction_type = data.get("type")
        # Code for handling different types of social interactions (chat forums, polls, social media integration)
        return jsonify({"message": "Social interaction ({}) for match {} has been recorded".format(interaction_type, match_id)}), 200
    else:
        return jsonify({"message": "Match not found"}), 404

if __name__ == "__main__":
    app.run()

User Interface: A responsive and intuitive web application interface to provide access to Crichd’s features.

Authentication and Authorization: A secure authentication system to verify user credentials and manage access control.

Content Management System: A robust CMS to handle content ingestion, storage, and metadata management.

Streaming Infrastructure: A scalable and reliable streaming infrastructure utilizing CDNs for efficient content delivery.

Recommendation Engine: A recommendation system that utilizes machine learning algorithms to personalize user recommendations based on their preferences and behavior.

Analytics and Monitoring: Tools and services to monitor system performance, track user behavior, and generate insights for further improvements.

Basic Low Level Design

  • GET /users/<user_id>: Retrieves user information based on the user ID.
  • POST /users: Creates a new user.
  • GET /matches/<match_id>: Retrieves match information based on the match ID.
  • GET /videos/<video_id>: Retrieves video information based on the video ID.
  • GET /likes/<like_id>: Retrieves like information based on the like ID.
  • GET /comments/<comment_id>: Retrieves comment information based on the comment ID.
class User:
    def __init__(self, user_id, username, password):
        self.user_id = user_id
        self.username = username
        self.password = password
        # Other user attributes

class Match:
    def __init__(self, match_id, team1, team2, venue, date, status):
        self.match_id = match_id
        self.team1 = team1
        self.team2 = team2
        self.venue = venue
        self.date = date
        self.status = status
        # Other match attributes

class Video:
    def __init__(self, video_id, match_id, video_url, caption, timestamp):
        self.video_id = video_id
        self.match_id = match_id
        self.video_url = video_url
        self.caption = caption
        self.timestamp = timestamp
        # Other video attributes

class Like:
    def __init__(self, like_id, user_id, video_id, timestamp):
        self.like_id = like_id
        self.user_id = user_id
        self.video_id = video_id
        self.timestamp = timestamp
        # Other like attributes

class Comment:
    def __init__(self, comment_id, user_id, video_id, caption_text, timestamp):
        self.comment_id = comment_id
        self.user_id = user_id
        self.video_id = video_id
        self.caption_text = caption_text
        self.timestamp = timestamp
        # Other comment attributes

User Management API:

  • Create User: This API allows creating a new user in the system.
  • Endpoint: POST /users
  • Request Body: { "username": "john", "email": "[email protected]", "password": "password" }
  • Response: { "message": "User created successfully" }

Get User: This API retrieves user information based on the user ID.

  • Endpoint: GET /users/{user_id}
  • Response: User object

Update User: This API updates user information based on the user ID.

  • Endpoint: PATCH /users/{user_id}
  • Request Body: { "username": "john_doe" }
  • Response: { "message": "User updated successfully" }

Match API:

  • Get Match: This API retrieves match information based on the match ID.
  • Endpoint: GET /matches/{match_id}
  • Response: Match object
  • Get Match Videos: This API retrieves videos related to a specific match.
  • Endpoint: GET /matches/{match_id}/videos
  • Response: List of Video objects

Video API:

  • Get Video: This API retrieves video information based on the video ID.
  • Endpoint: GET /videos/{video_id}
  • Response: Video object

Like Video: This API allows a user to like a video.

  • Endpoint: POST /videos/{video_id}/like
  • Request Body: { "user_id": "user1" }
  • Response: { "message": "Video liked successfully" }

Comment on Video: This API allows a user to comment on a video.

  • Endpoint: POST /videos/{video_id}/comment
  • Request Body: { "user_id": "user1", "comment": "Great shot!" }
  • Response: { "message": "Comment added successfully" }

Feed API:

  • Get User Feed: This API retrieves a user’s personalized feed.
  • Endpoint: GET /users/{user_id}/feed
  • Response: List of Video objects
from flask import Flask, jsonify, request
from datetime import datetime

app = Flask(__name__)

class User:
    def __init__(self, user_id, username, password):
        self.user_id = user_id
        self.username = username
        self.password = password

class Match:
    def __init__(self, match_id, team1, team2, venue, date, status):
        self.match_id = match_id
        self.team1 = team1
        self.team2 = team2
        self.venue = venue
        self.date = date
        self.status = status

class Video:
    def __init__(self, video_id, match_id, video_url, caption, timestamp):
        self.video_id = video_id
        self.match_id = match_id
        self.video_url = video_url
        self.caption = caption
        self.timestamp = timestamp

class Like:
    def __init__(self, like_id, user_id, video_id, timestamp):
        self.like_id = like_id
        self.user_id = user_id
        self.video_id = video_id
        self.timestamp = timestamp

class Comment:
    def __init__(self, comment_id, user_id, video_id, caption_text, timestamp):
        self.comment_id = comment_id
        self.user_id = user_id
        self.video_id = video_id
        self.caption_text = caption_text
        self.timestamp = timestamp

# Sample data
users = {
    "user1": User("user1", "John", "password1"),
    "user2": User("user2", "Alice", "password2")
}

matches = {
    "match1": Match("match1", "Team A", "Team B", "Stadium X", datetime.now(), "In Progress"),
    "match2": Match("match2", "Team C", "Team D", "Stadium Y", datetime.now(), "Upcoming")
}

videos = {
    "video1": Video("video1", "match1", "https://example.com/video1.mp4", "Great shot!", datetime.now()),
    "video2": Video("video2", "match2", "https://example.com/video2.mp4", "Amazing goal!", datetime.now())
}

likes = {
    "like1": Like("like1", "user1", "video1", datetime.now()),
    "like2": Like("like2", "user2", "video1", datetime.now())
}

comments = {
    "comment1": Comment("comment1", "user1", "video1", "Awesome!", datetime.now()),
    "comment2": Comment("comment2", "user2", "video1", "Well played!", datetime.now())
}

# User API endpoints
@app.route("/users/<user_id>", methods=["GET"])
def get_user(user_id):
    if user_id in users:
        user = users[user_id]
        return jsonify({"user_id": user.user_id, "username": user.username}), 200
    else:
        return jsonify({"message": "User not found"}), 404

@app.route("/users", methods=["POST"])
def create_user():
    data = request.json
    user_id = data["user_id"]
    username = data["username"]
    password = data["password"]
    user = User(user_id, username, password)
    users[user_id] = user
    return jsonify({"message": "User created successfully"}), 201

# Match API endpoints
@app.route("/matches/<match_id>", methods=["GET"])
def get_match(match_id):
    if match_id in matches:
        match = matches[match_id]
        return jsonify({"match_id": match.match_id, "team1": match.team1, "team2": match.team2}), 200
    else:
        return jsonify({"message": "Match not found"}), 404

# Video API endpoints
@app.route("/videos/<video_id>", methods=["GET"])
def get_video(video_id):
    if video_id in videos:
        video = videos[video_id]
        return jsonify({"video_id": video.video_id, "match_id": video.match_id, "caption": video.caption}), 200
    else:
        return jsonify({"message": "Video not found"}), 404

# Like API endpoints
@app.route("/likes/<like_id>", methods=["GET"])
def get_like(like_id):
    if like_id in likes:
        like = likes[like_id]
        return jsonify({"like_id": like.like_id, "user_id": like.user_id, "video_id": like.video_id}), 200
    else:
        return jsonify({"message": "Like not found"}), 404

# Comment API endpoints
@app.route("/comments/<comment_id>", methods=["GET"])
def get_comment(comment_id):
    if comment_id in comments:
        comment = comments[comment_id]
        return jsonify({"comment_id": comment.comment_id, "user_id": comment.user_id, "video_id": comment.video_id}), 200
    else:
        return jsonify({"message": "Comment not found"}), 404

if __name__ == "__main__":
    app.run()

API Design

User Authentication API:

  • Use Python’s Flask or Django framework to handle HTTP requests.
  • Implement functions for user login and registration, validating credentials, and generating access tokens or sessions.
  • Utilize authentication middleware to verify token/session validity before granting access to protected endpoints.

Match API:

  • Implement a function to fetch a list of matches from the database and serialize the data into JSON format for the response.
  • Create a function to retrieve detailed information about a specific match based on the provided match_id.

Player API:

  • Develop functions to retrieve player information from the database and serialize the data into JSON format.
  • Implement a function to fetch details about a specific player based on the provided player_id.

Streaming API:

  • Integrate a third-party streaming service (e.g., YouTube Live) to obtain the streaming URL for a particular match.
  • Implement a function to fetch the streaming URL or details from the streaming service based on the provided match_id.

Recommendation API:

  • Utilize machine learning models or collaborative filtering algorithms to generate personalized recommendations for users.
  • Develop a function to retrieve recommended matches or players based on the user’s preferences and serialize the data into JSON format.
from flask import Flask, jsonify, request

app = Flask(__name__)

# User Authentication API
@app.route('/api/auth/login', methods=['POST'])
def login():
    username = request.json.get('username')
    password = request.json.get('password')
    # Implement login logic here
    # Verify username and password, generate token/session
    return jsonify({'token': 'your_token_here'})

@app.route('/api/auth/register', methods=['POST'])
def register():
    username = request.json.get('username')
    password = request.json.get('password')
    email = request.json.get('email')
    # Implement registration logic here
    # Create new user, store credentials in the database
    return jsonify({'message': 'User registered successfully'})

# Match API
@app.route('/api/matches', methods=['GET'])
def get_matches():
    # Fetch matches from the database
    matches = [{'match_id': '1', 'team1': 'Team A', 'team2': 'Team B', 'start_time': '2023-07-10', 'end_time': '2023-07-12'}, 
               {'match_id': '2', 'team1': 'Team C', 'team2': 'Team D', 'start_time': '2023-07-13', 'end_time': '2023-07-15'}]
    return jsonify(matches)

@app.route('/api/matches/<match_id>', methods=['GET'])
def get_match(match_id):
    # Fetch match details from the database based on match_id
    match = {'match_id': match_id, 'team1': 'Team A', 'team2': 'Team B', 'venue': 'Stadium X', 'date': '2023-07-10', 'status': 'Live'}
    return jsonify(match)

# Player API
@app.route('/api/players', methods=['GET'])
def get_players():
    # Fetch players from the database
    players = [{'player_id': '1', 'name': 'Player A', 'team': 'Team A', 'country': 'Country X'}, 
               {'player_id': '2', 'name': 'Player B', 'team': 'Team B', 'country': 'Country Y'}]
    return jsonify(players)

@app.route('/api/players/<player_id>', methods=['GET'])
def get_player(player_id):
    # Fetch player details from the database based on player_id
    player = {'player_id': player_id, 'name': 'Player A', 'age': 28, 'batting_average': 45.75, 'bowling_average': 32.40}
    return jsonify(player)

# Streaming API
@app.route('/api/stream/<match_id>', methods=['GET'])
def get_stream(match_id):
    # Fetch streaming URL or details from the streaming service based on match_id
    stream = {'stream_url': 'your_stream_url_here'}
    return jsonify(stream)

# Recommendation API
@app.route('/api/recommendations/<user_id>', methods=['GET'])
def get_recommendations(user_id):
    # Fetch recommended matches or players for the user from the recommendation engine
    recommendations = [{'match_id': '1', 'team1': 'Team A', 'team2': 'Team B'}, 
                       {'match_id': '2', 'team1': 'Team C', 'team2': 'Team D'}]
    return jsonify(recommendations)

if __name__ == '__main__':
    app.run()

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

Live Streaming:

@app.route('/api/live_stream/<int:match_id>', methods=['GET'])
def live_stream(match_id):
    # Retrieve live streaming URL or details based on match_id
    streaming_url = get_streaming_url(match_id)
    if streaming_url:
        return jsonify({'stream_url': streaming_url})
    else:
        return jsonify({'message': 'Live streaming not available for this match'})

Match Highlights:

@app.route('/api/match_highlights/<int:match_id>', methods=['GET'])
def match_highlights(match_id):
    # Retrieve curated match highlights based on match_id
    highlights = get_match_highlights(match_id)
    if highlights:
        return jsonify({'highlights': highlights})
    else:
        return jsonify({'message': 'No highlights available for this match'})

Player Statistics:

@app.route('/api/player_stats/<int:player_id>', methods=['GET'])
def player_stats(player_id):
    # Retrieve player statistics based on player_id
    stats = get_player_statistics(player_id)
    if stats:
        return jsonify({'player_stats': stats})
    else:
        return jsonify({'message': 'Player statistics not available'})

Commentary and Analysis:

@app.route('/api/commentary/<int:match_id>', methods=['GET'])
def commentary(match_id):
    # Retrieve live commentary and analysis based on match_id
    commentary_data = get_commentary(match_id)
    if commentary_data:
        return jsonify({'commentary': commentary_data})
    else:
        return jsonify({'message': 'Commentary and analysis not available for this match'})

Social Interaction:

@app.route('/api/chat_forum', methods=['GET'])
def chat_forum():
    # Retrieve chat forum messages
    messages = get_chat_forum_messages()
    return jsonify({'messages': messages})
@app.route('/api/polls', methods=['GET'])
def polls():
    # Retrieve available polls
    polls_data = get_polls()
    return jsonify({'polls': polls_data})
@app.route('/api/social_media_integration', methods=['POST'])
def social_media_integration():
    # Handle social media integration logic
    # Process social media posts, comments, etc.
    return jsonify({'message': 'Social media integration successful'})

Personalization:

@app.route('/api/recommendations/<int:user_id>', methods=['GET'])
def recommendations(user_id):
    # Retrieve personalized recommendations for the user based on user_id
    recommendations = get_personalized_recommendations(user_id)
    return jsonify({'recommendations': recommendations})

System Design — Alibaba

We will be discussing in depth -

What is Alibaba

Alibaba is a multinational conglomerate and one of the world’s largest e-commerce companies. It was founded in 1999 by Jack Ma and is headquartered in Hangzhou, China. Alibaba operates various online platforms that facilitate business-to-business, business-to-consumer, and consumer-to-consumer transactions. It provides a wide range of services including e-commerce, retail, cloud computing, digital media, and entertainment.

Important Features

  • E-commerce Platform: Alibaba offers a robust and user-friendly e-commerce platform where businesses and individuals can buy and sell products and services.
  • Payment Systems: Alibaba has developed secure and reliable payment systems, such as Alipay, to facilitate online transactions.
  • Logistics and Supply Chain Management: The company has built a comprehensive logistics network to ensure efficient delivery and management of goods.
  • Cloud Computing: Alibaba Cloud provides scalable and reliable cloud computing services, including storage, networking, and data analytics.
  • Artificial Intelligence: Alibaba utilizes AI technologies for various purposes, such as personalized recommendations, image recognition, and natural language processing.
  • Cross-border Trade: Alibaba enables international trade by connecting global buyers and suppliers through its platforms, such as Alibaba.com and AliExpress.

Scaling Requirements — Capacity Estimation

For the sake of simplicity, let’s consider the following scenario:

  • Total number of users: 2 Billion
  • Daily active users (DAU): 500 million
  • Average number of products viewed by user/day: 5
  • Total number of products viewed per day: 2.5 Billion products/day
  • Read-to-write ratio: 100:1 (read-heavy system)
  • Total number of products uploaded/day: 1/100 * 2.5 Billion = 25 Million products/day

Storage Estimation:

  • Average size of each product: 100 KB
  • Total storage per day: 25 Million * 100 KB = 2.5 TB/day
  • For the next 3 years: 2.5 TB * 5 * 365 = 4.56 PB

Requests per second:

  • Number of read requests per second: 2.5 Billion / (3600 seconds * 24 hours) = 29.06K/sec

High Availability: The system should be designed to ensure maximum uptime and minimal service disruptions, even during peak traffic.

Elasticity: The infrastructure should be scalable horizontally and vertically to handle varying load demands.

Distributed Architecture: The system should be distributed across multiple regions and data centers to improve performance, fault tolerance, and reduce latency.

Load Balancing: Load balancing techniques should be implemented to distribute incoming traffic evenly across multiple servers.

Caching: Caching mechanisms, such as content delivery networks (CDNs) and in-memory caches, should be employed to reduce latency and improve response times.

Auto-scaling: Automated mechanisms should be in place to dynamically allocate resources based on demand, ensuring optimal resource utilization.

Data Model — ER requirements

User:

  • UserId: Int (Primary Key)
  • Username: String
  • Email: String
  • Password: String

Product:

  • ProductId: Int (Primary Key)
  • SellerId: Int (Foreign Key referencing User.UserId)
  • Name: String
  • Description: String
  • Price: Decimal
  • Inventory: Int

Order:

  • OrderId: Int (Primary Key)
  • UserId: Int (Foreign Key referencing User.UserId)
  • ProductId: Int (Foreign Key referencing Product.ProductId)
  • Quantity: Int
  • OrderDate: DateTime

Review:

  • ReviewId: Int (Primary Key)
  • UserId: Int (Foreign Key referencing User.UserId)
  • ProductId: Int (Foreign Key referencing Product.ProductId)
  • Rating: Int
  • Comment: String
  • ReviewDate: DateTime

High Level Design

Assumptions:

  • The system should handle a high volume of concurrent users.
  • The system should be horizontally scalable to accommodate increasing user demands.
  • Availability and reliability are crucial aspects of the system.
  • Caching and load balancing mechanisms should be implemented for performance optimization.
  • Security measures, such as encryption and authentication, need to be in place to protect user data.

Main Components and Services:

User Management:

  • User registration and authentication services.
  • User profile management (username, email, password).
  • User authorization and access control.

Product Management:

  • Product listing, creation, and modification services.
  • Inventory management and tracking.
  • Product search and filtering functionality.

Order Management:

  • Order placement and processing services.
  • Order tracking and status updates.
  • Payment processing and integration with secure payment systems.

Reviews and Ratings:

  • Review submission and management services.
  • Rating calculation and aggregation.
  • Integration with the product detail page to display reviews.

Search and Recommendation:

  • Search functionality to allow users to find products based on keywords, categories, and other attributes.
  • Recommendation engine to provide personalized product recommendations based on user preferences and behavior.

Caching and Load Balancing:

  • Implement caching mechanisms to improve response times and reduce database load.
  • Utilize load balancers to distribute incoming traffic across multiple servers for better performance and fault tolerance.

Security and Privacy:

  • Implement encryption and secure communication protocols (e.g., HTTPS) to protect sensitive user data.
  • Ensure proper user authentication and authorization mechanisms to safeguard user accounts.
  • Apply data privacy measures and comply with relevant regulations (e.g., GDPR) to protect user privacy.
# User Management Service
class UserManagementService:
    def register_user(self, username, email, password):
        # Logic for user registration
        user_id = generate_user_id()
        user = User(user_id, username, email, password)
        save_user_to_database(user)
        return user_id

    def authenticate_user(self, email, password):
        # Logic for user authentication
        user = get_user_by_email(email)
        if user is not None and user.password == password:
            return user.user_id
        return None

    def update_user_profile(self, user_id, username, email, password):
        # Logic for updating user profile
        user = get_user_by_id(user_id)
        if user is not None:
            user.username = username
            user.email = email
            user.password = password
            save_user_to_database(user)
            return True
        return False

# Product Management Service
class ProductManagementService:
    def create_product(self, seller_id, name, description, price, inventory):
        # Logic for creating a new product
        product_id = generate_product_id()
        product = Product(product_id, seller_id, name, description, price, inventory)
        save_product_to_database(product)
        return product_id

    def update_product(self, product_id, name, description, price, inventory):
        # Logic for updating product details
        product = get_product_by_id(product_id)
        if product is not None:
            product.name = name
            product.description = description
            product.price = price
            product.inventory = inventory
            save_product_to_database(product)
            return True
        return False

    def search_products(self, keyword):
        # Logic for searching products based on a keyword
        products = search_products_by_keyword(keyword)
        return products

# Order Management Service
class OrderManagementService:
    def place_order(self, user_id, product_id, quantity):
        # Logic for placing an order
        product = get_product_by_id(product_id)
        if product is not None and product.inventory >= quantity:
            order_id = generate_order_id()
            order = Order(order_id, user_id, product_id, quantity)
            save_order_to_database(order)
            reduce_product_inventory(product_id, quantity)
            return order_id
        return None

    def get_order_status(self, order_id):
        # Logic for getting the status of an order
        order = get_order_by_id(order_id)
        if order is not None:
            return order.status
        return None

# Review and Rating Service
class ReviewRatingService:
    def submit_review(self, user_id, product_id, rating, comment):
        # Logic for submitting a review
        review_id = generate_review_id()
        review = Review(review_id, user_id, product_id, rating, comment)
        save_review_to_database(review)
        return review_id

    def get_product_reviews(self, product_id):
        # Logic for retrieving reviews of a product
        reviews = get_reviews_by_product_id(product_id)
        return reviews

# Example usage of the services
user_service = UserManagementService()
product_service = ProductManagementService()
order_service = OrderManagementService()
review_service = ReviewRatingService()

# User Management Service
user_id = user_service.register_user("username", "[email protected]", "password")
authenticated_user_id = user_service.authenticate_user("[email protected]", "password")
user_service.update_user_profile(user_id, "new_username", "[email protected]", "new_password")

# Product Management Service
product_id = product_service.create_product(seller_id, "Product Name", "Product Description", 9.99, 100)
product_service.update_product(product_id, "New Product Name", "New Product Description", 19.99, 50)
search_results = product_service.search_products("keyword")

# Order Management Service
order_id = order_service.place_order(user_id, product_id, 2)
order_status = order_service.get_order_status(order_id)

# Review and Rating Service
review_id = review_service.submit_review(user_id, product_id, 4, "Great product!")
product_reviews = review_service.get_product_reviews(product_id)

Microservices Architecture: Alibaba’s system can be designed using a microservices architecture to ensure modularity, scalability, and fault isolation.

Service Orchestration: A service orchestration layer can be implemented to coordinate communication and workflows between different microservices.

Distributed Storage: Alibaba can leverage distributed storage systems, such as NoSQL databases or distributed file systems, to handle large volumes of data and provide high availability.

Message Queues: A message queue system can be used to decouple components and enable asynchronous processing of tasks.

Content Delivery Networks (CDNs): CDNs can be employed to cache and serve static content efficiently, reducing latency and network congestion.

Basic Low Level Design

class User:
    def __init__(self, user_id, username, password):
        self.user_id = user_id
        self.username = username
        self.password = password
        # other user attributes

class Product:
    def __init__(self, product_id, seller_id, name, price, inventory):
        self.product_id = product_id
        self.seller_id = seller_id
        self.name = name
        self.price = price
        self.inventory = inventory
        # other product attributes

class Alibaba:
    def __init__(self):
        self.users = {}
        self.products = []

    def add_user(self, user):
        self.users[user.user_id] = user

    def get_user_by_id(self, user_id):
        return self.users.get(user_id)

    def create_product(self, seller_id, name, price, inventory):
        product_id = len(self.products) + 1
        product = Product(product_id, seller_id, name, price, inventory)
        self.products.append(product)

    # Additional methods for searching, purchasing, and managing products

API Design

User Management API:

  • Endpoint: /users
  • Methods: POST
  • Description: This API allows users to create a new account.
  • Request Payload:
  • { "username": "john_doe", "password": "password123" }
  • Response: HTTP status code indicating the success or failure of the account creation process.
from flask import Flask, request
app = Flask(__name__)
alibaba = Alibaba()
@app.route("/users", methods=["POST"])
def create_user():
    data = request.get_json()
    user_id = len(alibaba.users) + 1
    user = User(user_id, data["username"], data["password"])
    alibaba.add_user(user)
    return {"message": "User created successfully"}, 201

Product Management API:

  • Endpoint: /products
  • Methods: POST
  • Description: This API allows sellers to create a new product listing.
  • Request Payload:
  • { "seller_id": 1, "name": "Product A", "price": 9.99, "inventory": 100 }
  • Response: HTTP status code indicating the success or failure of the product creation process.
@app.route("/products", methods=["POST"])
def create_product():
    data = request.get_json()
    seller_id = data["seller_id"]
    name = data["name"]
    price = data["price"]
    inventory = data["inventory"]
    alibaba.create_product(seller_id, name, price, inventory)
    return {"message": "Product created successfully"}, 201

Product Search API:

  • Endpoint: /products
  • Methods: GET
  • Description: This API allows users to search for products based on various criteria.
  • Request Parameters:
  • query: The search query entered by the user (optional).
  • category: The category of products to filter the search results (optional).
  • Response: A list of products matching the search criteria.
@app.route("/products", methods=["GET"])
def search_products():
    query = request.args.get("query")
    category = request.args.get("category")
    # Perform product search based on query and category
    # Return the search results as a JSON response
    return {"results": search_results}

Product Purchase API:

  • Endpoint: /products/{product_id}/purchase
  • Methods: POST
  • Description: This API allows users to purchase a specific product.
  • Request Parameters:
  • product_id: The ID of the product to purchase.
  • user_id: The ID of the user making the purchase.
  • quantity: The quantity of the product to purchase.
  • Response: HTTP status code indicating the success or failure of the purchase process.
@app.route("/products/<int:product_id>/purchase", methods=["POST"])
def purchase_product(product_id):
    data = request.get_json()
    user_id = data["user_id"]
    quantity = data["quantity"]
    # Perform the purchase logic
    # Return the purchase status as a JSON response
    return {"message": "Purchase successful"}
# Import necessary libraries
from flask import Flask, request, jsonify

# Create Flask application
app = Flask(__name__)

# Define endpoint for product listing
@app.route('/products', methods=['GET'])
def get_product_list():
    # Retrieve query parameters
    category = request.args.get('category')
    min_price = request.args.get('min_price')
    max_price = request.args.get('max_price')

    # Perform filtering based on query parameters (simplified example)
    filtered_products = filter_products(category, min_price, max_price)

    # Prepare response data
    response = {
        'status': 'success',
        'data': filtered_products
    }

    # Return JSON response
    return jsonify(response), 200

# Helper function for filtering products (simplified example)
def filter_products(category, min_price, max_price):
    # Perform actual filtering based on provided parameters
    # (This function would typically interact with the database or data storage)

    # Placeholder example with static data
    products = [
        {'id': 1, 'name': 'Product 1', 'price': 100, 'category': 'Electronics'},
        {'id': 2, 'name': 'Product 2', 'price': 50, 'category': 'Clothing'},
        {'id': 3, 'name': 'Product 3', 'price': 200, 'category': 'Electronics'},
        {'id': 4, 'name': 'Product 4', 'price': 150, 'category': 'Home'},
    ]

    filtered_products = []
    for product in products:
        if (not category or product['category'] == category) and \
                (not min_price or product['price'] >= int(min_price)) and \
                (not max_price or product['price'] <= int(max_price)):
            filtered_products.append(product)

    return filtered_products

# Run the Flask application
if __name__ == '__main__':
    app.run()
from flask import Flask
from flask_restful import Api, Resource, reqparse

app = Flask(__name__)
api = Api(app)

# Define request parser for validation
product_parser = reqparse.RequestParser()
product_parser.add_argument('category', type=str)
product_parser.add_argument('min_price', type=float)
product_parser.add_argument('max_price', type=float)

# Define the ProductList resource
class ProductList(Resource):
    def get(self):
        # Parse and validate the request arguments
        args = product_parser.parse_args()

        # Perform filtering based on request arguments (simplified example)
        filtered_products = filter_products(args['category'], args['min_price'], args['max_price'])

        # Prepare response data
        response = {
            'status': 'success',
            'data': filtered_products
        }

        return response, 200

# Helper function for filtering products (simplified example)
def filter_products(category, min_price, max_price):
    # Perform actual filtering based on provided parameters
    # (This function would typically interact with the database or data storage)

    # Placeholder example with static data
    products = [
        {'id': 1, 'name': 'Product 1', 'price': 100, 'category': 'Electronics'},
        {'id': 2, 'name': 'Product 2', 'price': 50, 'category': 'Clothing'},
        {'id': 3, 'name': 'Product 3', 'price': 200, 'category': 'Electronics'},
        {'id': 4, 'name': 'Product 4', 'price': 150, 'category': 'Home'},
    ]

    filtered_products = []
    for product in products:
        if (not category or product['category'] == category) and \
                (not min_price or product['price'] >= min_price) and \
                (not max_price or product['price'] <= max_price):
            filtered_products.append(product)

    return filtered_products

# Add the ProductList resource to the API with its corresponding URL
api.add_resource(ProductList, '/products')

# Run the Flask application
if __name__ == '__main__':
    app.run()

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

E-commerce Platform:

class EcommercePlatform:
    def __init__(self):
        self.products = []
    def add_product(self, product):
        self.products.append(product)
    def remove_product(self, product):
        self.products.remove(product)
    def get_products(self):
        return self.products
# Usage example:
platform = EcommercePlatform()
platform.add_product("Product 1")
platform.add_product("Product 2")
print(platform.get_products())
platform.remove_product("Product 1")
print(platform.get_products())

Payment Systems:

class PaymentSystem:
    def __init__(self):
        self.balance = 0
    def deposit(self, amount):
        self.balance += amount
    def withdraw(self, amount):
        if self.balance >= amount:
            self.balance -= amount
        else:
            print("Insufficient balance")
    def get_balance(self):
        return self.balance
# Usage example:
payment_system = PaymentSystem()
payment_system.deposit(1000)
payment_system.withdraw(500)
print(payment_system.get_balance())

Logistics and Supply Chain Management:

class LogisticsManager:
    def __init__(self):
        self.packages = []
    def add_package(self, package):
        self.packages.append(package)
    def remove_package(self, package):
        self.packages.remove(package)
    def get_packages(self):
        return self.packages
# Usage example:
logistics_manager = LogisticsManager()
logistics_manager.add_package("Package 1")
logistics_manager.add_package("Package 2")
print(logistics_manager.get_packages())
logistics_manager.remove_package("Package 1")
print(logistics_manager.get_packages())

Cloud Computing:

class CloudComputing:
    def __init__(self):
        self.storage = []
        self.networking = []
        self.data_analytics = []
    def add_storage(self, storage):
        self.storage.append(storage)
    def add_networking(self, networking):
        self.networking.append(networking)
    def add_data_analytics(self, data_analytics):
        self.data_analytics.append(data_analytics)
    def get_storage(self):
        return self.storage
    def get_networking(self):
        return self.networking
    def get_data_analytics(self):
        return self.data_analytics
# Usage example:
cloud_computing = CloudComputing()
cloud_computing.add_storage("Storage 1")
cloud_computing.add_networking("Networking 1")
cloud_computing.add_data_analytics("Data Analytics 1")
print(cloud_computing.get_storage())
print(cloud_computing.get_networking())
print(cloud_computing.get_data_analytics())

Artificial Intelligence:

class ArtificialIntelligence:
    def __init__(self):
        self.recommendations = []
        self.image_recognition = []
        self.nlp = []
    def add_recommendation(self, recommendation):
        self.recommendations.append(recommendation)
    def add_image_recognition(self, image_recognition):
        self.image_recognition.append(image_recognition)
    def add_nlp(self, nlp):
        self.nlp.append(nlp)
    def get_recommendations(self):
        return self.recommendations
    def get_image_recognition(self):
        return self.image_recognition
    def get_nlp(self):
        return self.nlp
# Usage example:
ai = ArtificialIntelligence()
ai.add_recommendation("Recommendation 1")
ai.add_image_recognition("Image Recognition 1")
ai.add_nlp("Natural Language Processing 1")
print(ai.get_recommendations())
print(ai.get_image_recognition())
print(ai.get_nlp())

Cross-border Trade:

class CrossBorderTrade:
    def __init__(self):
        self.buyers = []
        self.suppliers = []
    def add_buyer(self, buyer):
        self.buyers.append(buyer)
    def add_supplier(self, supplier):
        self.suppliers.append(supplier)
    def get_buyers(self):
        return self.buyers
    def get_suppliers(self):
        return self.suppliers
# Usage example:
cross_border_trade = CrossBorderTrade()
cross_border_trade.add_buyer("Buyer 1")
cross_border_trade.add_buyer("Buyer 2")
cross_border_trade.add_supplier("Supplier 1")
print(cross_border_trade.get_buyers())
print(cross_border_trade.get_suppliers())

System Design — Substack

We will be discussing in depth -

Pic credits : Pinterest

What is Substack

Substack is a subscription-based publishing platform that enables writers to create and distribute newsletters to their audience. It provides a user-friendly interface for authors to compose and publish their content, while allowing readers to subscribe to their favorite newsletters and receive regular updates via email. Substack also offers monetization options, allowing authors to charge for premium content or offer paid subscriptions.

Important Features

  • User Registration and Authentication: Substack provides a seamless user registration process and ensures secure authentication for both authors and readers.
  • Newsletter Creation and Publishing: Authors can compose, format, and publish newsletters using a rich text editor with features like embedding media, adding images, and organizing content.
  • Subscription Management: Readers can easily discover and subscribe to newsletters of their interest, manage their subscription preferences, and receive email notifications for new issues.
  • Monetization Options: Substack facilitates monetization by enabling authors to offer paid subscriptions, create premium content, or receive voluntary contributions from readers.
  • Audience Interaction: Substack allows readers to engage with authors through comments, feedback, and replies, fostering a sense of community.
  • Analytics and Insights: Authors can access analytics to track newsletter performance, including subscriber growth, open rates, and engagement metrics.

Scaling Requirements — Capacity Estimation

Let’s assume —

  1. Total number of users: 10 million
  2. Daily active users (DAU): 2 million
  3. Average number of newsletters read by a user per day: 2
  4. Total number of newsletters read per day: 4 million newsletters/day
  5. Read-to-write ratio: 100:1 (as in the Netflix example)
  6. Total number of newsletters created per day: 1/100 * 4 million = 40,000 newsletters/day

Storage Estimation: Let’s assume an average newsletter size of 1 MB.

Total storage per day: 40,000 newsletters * 1 MB = 40 GB/day

For the next 3 years: 40 GB * 365 days * 3 years = 43.8 TB

Requests per second: 4 million newsletters / (3600 seconds * 24 hours) = 46 newsletters/second

Horizontal Scalability: The platform should be designed to handle a high volume of concurrent user interactions, such as reading newsletters, subscribing, and commenting.

Content Distribution: Efficient content delivery mechanisms, like content caching and content delivery networks (CDNs), should be employed to serve newsletters to readers across different geographical regions.

Robust Data Storage: The system should employ scalable and fault-tolerant databases to handle large amounts of user-generated content, including newsletters, user profiles, and subscription data.

Data Model — ER requirements

Users:

  • Username: String
  • Email: String
  • Password: String

Posts:

  • PostId: Int
  • User_id: Int (Foreign key referencing Users table)
  • Content: String
  • Timestamp: DateTime

Likes:

  • Like_id: Int
  • User_id: Int (Foreign key referencing Users table)
  • Post_id: Int (Foreign key referencing Posts table)
  • Timestamp: DateTime

Comments:

  • Comment_id: Int
  • Post_id: Int (Foreign key referencing Posts table)
  • User_id: Int (Foreign key referencing Users table)
  • Caption_text: String
  • Timestamp: DateTime

High Level Design

Assumptions:

  1. There will be more reads than writes, so the system should be optimized for read operations.
  2. Horizontal scaling will be used to handle increasing user demand.
  3. High availability and reliability are crucial for the system.
  4. Latency for feed generation should be around 350ms.
  5. Consistency and reliability are more important than strict consistency.

Main Components and Services:

Mobile Client:

  • Represents users accessing Substack via mobile devices.

Application Servers:

  • Responsible for handling read and write operations, as well as notification services.

Load Balancer:

  • Routes and directs requests to the appropriate servers based on the designated services.

Cache (e.g., Memcache):

  • Utilized to improve performance by caching frequently accessed data based on the Least Recently Used (LRU) strategy.

CDN (Content Delivery Network):

  • Enhances latency and throughput by caching and delivering static content closer to the users.

Database:

  • Stores data based on the defined data model, allowing for efficient retrieval and storage.
  • NoSQL databases, like MongoDB or Cassandra, may be suitable for storing key-value pairs and capturing entity relationships.

Storage (e.g., Amazon S3):

  • Used to upload and store photos, providing a reliable and scalable solution.

Services:

Like Service:

  • Enables users to like a specific post.
  • Utilizes the data model to associate users with posts and timestamps.

Follow Service:

  • Allows users to follow other users.
  • Captures the relationship between User_id1 and User_id2.

Comment Service:

  • Provides functionality for users to comment on posts and reply to prior comments.
  • Stores the comment text, timestamps, and associations with the respective post and user.

Post Service:

  • Handles the creation and storage of posts.
  • Stores the post content, timestamps, and associations with the respective user.

Generate Feed Service:

  • Fetches recent, popular, and relevant posts from the users that the current user follows.
  • Utilizes ranking algorithms to score posts based on factors like likes, comments, and user activity.
  • Generates and stores user-specific feeds for efficient retrieval during login.
from datetime import datetime

# User service
class UserService:
    def __init__(self):
        self.users = []

    def register_user(self, username, email, password):
        user = {
            'username': username,
            'email': email,
            'password': password
        }
        self.users.append(user)

    def get_user_by_username(self, username):
        for user in self.users:
            if user['username'] == username:
                return user
        return None

# Post service
class PostService:
    def __init__(self):
        self.posts = []
        self.post_id = 1

    def create_post(self, user_id, content):
        post = {
            'post_id': self.post_id,
            'user_id': user_id,
            'content': content,
            'timestamp': datetime.now()
        }
        self.posts.append(post)
        self.post_id += 1
        return post

    def get_post_by_id(self, post_id):
        for post in self.posts:
            if post['post_id'] == post_id:
                return post
        return None

# Like service
class LikeService:
    def __init__(self):
        self.likes = []
        self.like_id = 1

    def add_like(self, user_id, post_id):
        like = {
            'like_id': self.like_id,
            'user_id': user_id,
            'post_id': post_id,
            'timestamp': datetime.now()
        }
        self.likes.append(like)
        self.like_id += 1

    def get_likes_for_post(self, post_id):
        return [like for like in self.likes if like['post_id'] == post_id]

# Comment service
class CommentService:
    def __init__(self):
        self.comments = []
        self.comment_id = 1

    def add_comment(self, user_id, post_id, caption_text):
        comment = {
            'comment_id': self.comment_id,
            'user_id': user_id,
            'post_id': post_id,
            'caption_text': caption_text,
            'timestamp': datetime.now()
        }
        self.comments.append(comment)
        self.comment_id += 1

    def get_comments_for_post(self, post_id):
        return [comment for comment in self.comments if comment['post_id'] == post_id]

# Follow service
class FollowService:
    def __init__(self):
        self.follows = []

    def add_follow(self, user_id1, user_id2):
        follow = {
            'user_id1': user_id1,
            'user_id2': user_id2
        }
        self.follows.append(follow)

    def get_followers_for_user(self, user_id):
        return [follow['user_id1'] for follow in self.follows if follow['user_id2'] == user_id]

    def get_following_for_user(self, user_id):
        return [follow['user_id2'] for follow in self.follows if follow['user_id1'] == user_id]

# Usage example
user_service = UserService()
post_service = PostService()
like_service = LikeService()
comment_service = CommentService()
follow_service = FollowService()

# Register users
user_service.register_user('user1', '[email protected]', 'password1')
user_service.register_user('user2', '[email protected]', 'password2')

# Create posts
post1 = post_service.create_post(1, 'This is my first post!')
post2 = post_service.create_post(2, 'Hello world!')

# Add likes
like_service.add_like(1, 1)
like_service.add_like(2, 1)

# Add comments
comment_service.add_comment(1, 1, 'Great post!')
comment_service.add_comment(2, 1, 'Nice!')

# Add follows
follow_service.add_follow(1, 2)

# Retrieve user-specific data
user1 = user_service.get_user_by_username('user1')
user2 = user_service.get_user_by_username('user2')
post1_likes = like_service.get_likes_for_post(1)
post1_comments = comment_service.get_comments_for_post(1)
user1_followers = follow_service.get_followers_for_user(1)
user1_following = follow_service.get_following_for_user(1)

print("User 1:", user1)
print("User 2:", user2)
print("Likes for Post 1:", post1_likes)
print("Comments for Post 1:", post1_comments)
print("User 1's followers:", user1_followers)
print("User 1's following:", user1_following)

Frontend Application: Responsible for the user interface, providing authoring tools, subscription management, and reader interactions.

Backend Services: Handle core functionalities like user authentication, newsletter creation, content storage, subscription management, and payment processing.

Databases: Store user profiles, newsletter metadata, subscriptions, comments, and payment information.

Caching and CDN: Improve content delivery performance by caching frequently accessed newsletters and utilizing CDN services for global distribution.

Basic Low Level Design

from flask import Flask, request

app = Flask(__name__)

class User:
    def __init__(self, user_id, username, password):
        self.user_id = user_id
        self.username = username
        self.password = password
        # other user attributes

class Newsletter:
    def __init__(self, newsletter_id, author, title):
        self.newsletter_id = newsletter_id
        self.author = author
        self.title = title
        # other newsletter attributes

class Substack:
    def __init__(self):
        self.users = []
        self.newsletters = []

    def add_user(self, user):
        self.users.append(user)

    def add_newsletter(self, newsletter):
        self.newsletters.append(newsletter)

substack = Substack()

@app.route('/users', methods=['POST'])
def register_user():
    data = request.get_json()
    user_id = len(substack.users) + 1
    user = User(user_id, data['username'], data['password'])
    substack.add_user(user)
    return {
        'user_id': user.user_id,
        'message': 'User registered successfully'
    }

@app.route('/newsletters', methods=['POST'])
def create_newsletter():
    data = request.get_json()
    newsletter_id = len(substack.newsletters) + 1
    newsletter = Newsletter(newsletter_id, data['author'], data['title'])
    substack.add_newsletter(newsletter)
    return {
        'newsletter_id': newsletter.newsletter_id,
        'message': 'Newsletter created successfully'
    }

@app.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
    for user in substack.users:
        if user.user_id == user_id:
            return {
                'user_id': user.user_id,
                'username': user.username,
                'password': user.password
            }
    return 'User not found', 404

@app.route('/newsletters/<int:newsletter_id>', methods=['GET'])
def get_newsletter(newsletter_id):
    for newsletter in substack.newsletters:
        if newsletter.newsletter_id == newsletter_id:
            return {
                'newsletter_id': newsletter.newsletter_id,
                'author': newsletter.author,
                'title': newsletter.title
            }
    return 'Newsletter not found', 404

@app.route('/users/<int:user_id>/subscribe/<int:newsletter_id>', methods=['POST'])
def subscribe_to_newsletter(user_id, newsletter_id):
    user = None
    newsletter = None

    for u in substack.users:
        if u.user_id == user_id:
            user = u
            break

    for n in substack.newsletters:
        if n.newsletter_id == newsletter_id:
            newsletter = n
            break

    if user and newsletter:
        # Perform subscription logic
        return 'User subscribed to the newsletter'
    else:
        return 'User or newsletter not found', 404

@app.route('/users/<int:user_id>/unsubscribe/<int:newsletter_id>', methods=['POST'])
def unsubscribe_from_newsletter(user_id, newsletter_id):
    user = None
    newsletter = None

    for u in substack.users:
        if u.user_id == user_id:
            user = u
            break

    for n in substack.newsletters:
        if n.newsletter_id == newsletter_id:
            newsletter = n
            break

    if user and newsletter:
        # Perform unsubscription logic
        return 'User unsubscribed from the newsletter'
    else:
        return 'User or newsletter not found', 404

if __name__ == '__main__':
    app.run()

API Design

User Management API: This API handles user-related operations, including registration, login, and profile management.

from flask import Flask, request
app = Flask(__name__)
@app.route('/api/register', methods=['POST'])
def register_user():
    # Handle user registration logic
    username = request.json['username']
    email = request.json['email']
    password = request.json['password']
    # Perform registration process
    # Return success response or appropriate error message
@app.route('/api/login', methods=['POST'])
def login_user():
    # Handle user login logic
    username = request.json['username']
    password = request.json['password']
    # Perform login process
    # Return success response or appropriate error message
@app.route('/api/user/profile', methods=['GET'])
def get_user_profile():
    # Handle fetching user profile logic
    user_id = request.args.get('user_id')
    # Retrieve user profile information from the database
    # Return user profile data or appropriate error message
if __name__ == '__main__':
    app.run()

Newsletter API: This API enables authors to create, edit, and retrieve newsletters.

from flask import Flask, request
app = Flask(__name__)
@app.route('/api/newsletter', methods=['POST'])
def create_newsletter():
    # Handle creating a new newsletter
    author_id = request.json['author_id']
    title = request.json['title']
    content = request.json['content']
    # Perform newsletter creation process
    # Return success response or appropriate error message
@app.route('/api/newsletter/<newsletter_id>', methods=['PUT'])
def edit_newsletter(newsletter_id):
    # Handle editing an existing newsletter
    title = request.json['title']
    content = request.json['content']
    # Perform newsletter editing process
    # Return success response or appropriate error message
@app.route('/api/newsletter/<newsletter_id>', methods=['GET'])
def get_newsletter(newsletter_id):
    # Handle fetching a specific newsletter
    # Retrieve newsletter data from the database
    # Return newsletter data or appropriate error message
if __name__ == '__main__':
    app.run()
from flask import Flask, request
from low_level_api import register_user, login_user, get_user_profile, create_newsletter, edit_newsletter, get_newsletter
app = Flask(__name__)
@app.route('/api/user/register', methods=['POST'])
def high_level_register_user():
    return register_user(request.json)
@app.route('/api/user/login', methods=['POST'])
def high_level_login_user():
    return login_user(request.json)
@app.route('/api/user/profile', methods=['GET'])
def high_level_get_user_profile():
    user_id = request.args.get('user_id')
    return get_user_profile(user_id)
@app.route('/api/newsletter', methods=['POST'])
def high_level_create_newsletter():
    return create_newsletter(request.json)
@app.route('/api/newsletter/<newsletter_id>', methods=['PUT'])
def high_level_edit_newsletter(newsletter_id):
    return edit_newsletter(newsletter_id, request.json)
@app.route('/api/newsletter/<newsletter_id>', methods=['GET'])
def high_level_get_newsletter(newsletter_id):
    return get_newsletter(newsletter_id)
if __name__ == '__main__':
    app.run()

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

User Registration and Authentication:

class User:
    def __init__(self, username, email, password):
        self.username = username
        self.email = email
        self.password = password
class Substack:
    def __init__(self):
        self.users = []
    def register_user(self, username, email, password):
        user = User(username, email, password)
        self.users.append(user)
    def authenticate_user(self, username, password):
        for user in self.users:
            if user.username == username and user.password == password:
                return True
        return False
substack = Substack()
substack.register_user("john_doe", "[email protected]", "password123")
authenticated = substack.authenticate_user("john_doe", "password123")
print("Authentication successful:", authenticated)

Newsletter Creation and Publishing:

class Newsletter:
    def __init__(self, author, title, content):
        self.author = author
        self.title = title
        self.content = content
class Substack:
    def __init__(self):
        self.newsletters = []
    def create_newsletter(self, author, title, content):
        newsletter = Newsletter(author, title, content)
        self.newsletters.append(newsletter)
    def publish_newsletter(self, newsletter):
        print("Publishing Newsletter")
        print("Author:", newsletter.author)
        print("Title:", newsletter.title)
        print("Content:", newsletter.content)
substack = Substack()
substack.create_newsletter("John Doe", "Weekly Digest", "Lorem ipsum dolor sit amet...")
newsletter = substack.newsletters[0]
substack.publish_newsletter(newsletter)

Subscription Management:

class User:
    def __init__(self, username):
        self.username = username
        self.subscriptions = []
    def subscribe_to_newsletter(self, newsletter):
        self.subscriptions.append(newsletter)
    def unsubscribe_from_newsletter(self, newsletter):
        self.subscriptions.remove(newsletter)
class Substack:
    def __init__(self):
        self.users = []
        self.newsletters = []
    def create_newsletter(self, author, title, content):
        newsletter = Newsletter(author, title, content)
        self.newsletters.append(newsletter)
    def subscribe_user_to_newsletter(self, username, newsletter_title):
        user = self.get_user(username)
        newsletter = self.get_newsletter(newsletter_title)
        if user and newsletter:
            user.subscribe_to_newsletter(newsletter)
    def unsubscribe_user_from_newsletter(self, username, newsletter_title):
        user = self.get_user(username)
        newsletter = self.get_newsletter(newsletter_title)
        if user and newsletter:
            user.unsubscribe_from_newsletter(newsletter)
    def get_user(self, username):
        for user in self.users:
            if user.username == username:
                return user
        return None
    def get_newsletter(self, title):
        for newsletter in self.newsletters:
            if newsletter.title == title:
                return newsletter
        return None

Monetization Options: (Example with paid subscriptions)

class User:
    def __init__(self, username):
        self.username = username
        self.subscriptions = []
        self.paid_subscriptions = []
    def subscribe_to_newsletter(self, newsletter):
        self.subscriptions.append(newsletter)
    def purchase_paid_subscription(self, newsletter):
        self.paid_subscriptions.append(newsletter)
class Substack:
    def __init__(self):
        self.users = []
        self.newsletters = []
    def create_newsletter(self, author, title, content):
        newsletter = Newsletter(author, title, content)
        self.newsletters.append(newsletter)
    def subscribe_user_to_newsletter(self, username, newsletter_title):
        user = self.get_user(username)
        newsletter = self.get_newsletter(newsletter_title)
        if user and newsletter:
            user.subscribe_to_newsletter(newsletter)
    def purchase_subscription(self, username, newsletter_title):
        user = self.get_user(username)
        newsletter = self.get_newsletter(newsletter_title)
        if user and newsletter:
            user.purchase_paid_subscription(newsletter)
    def get_user(self, username):
        for user in self.users:
            if user.username == username:
                return user
        return None
    def get_newsletter(self, title):
        for newsletter in self.newsletters:
            if newsletter.title == title:
                return newsletter
        return None

Audience Interaction:

class Comment:
    def __init__(self, user, content):
        self.user = user
        self.content = content
class Newsletter:
    def __init__(self, author, title, content):
        self.author = author
        self.title = title
        self.content = content
        self.comments = []
    def add_comment(self, user, content):
        comment = Comment(user, content)
        self.comments.append(comment)
class Substack:
    def __init__(self):
        self.newsletters = []
    def create_newsletter(self, author, title, content):
        newsletter = Newsletter(author, title, content)
        self.newsletters.append(newsletter)
    def add_comment_to_newsletter(self, newsletter_title, user, content):
        newsletter = self.get_newsletter(newsletter_title)
        if newsletter:
            newsletter.add_comment(user, content)
    def get_newsletter(self, title):
        for newsletter in self.newsletters:
            if newsletter.title == title:
                return newsletter
        return None
substack = Substack()

Analytics and Insights:

class Newsletter:
    def __init__(self, author, title, content):
        self.author = author
        self.title = title
        self.content = content
        self.subscribers = []
    def add_subscriber(self, user):
        self.subscribers.append(user)
    def get_subscriber_count(self):
        return len(self.subscribers)
class Substack:
    def __init__(self):
        self.newsletters = []
    def create_newsletter(self, author, title, content):
        newsletter = Newsletter(author, title, content)
        self.newsletters.append(newsletter)
    def subscribe_user_to_newsletter(self, newsletter_title, user):
        newsletter = self.get_newsletter(newsletter_title)
        if newsletter:
            newsletter.add_subscriber(user)
    def get_newsletter(self, title):
        for newsletter in self.newsletters:
            if newsletter.title == title:
                return newsletter
        return None
substack = Substack()

System Design — Instant Messenger

We will be discussing in depth -

Pic credits : Pinterest

What is Instant Messenger

Instant Messenger (IM) is a real-time communication application that enables users to exchange text messages, multimedia files, and other content over the internet. It facilitates instant, one-to-one or group messaging between individuals and allows for seamless and quick interactions.

Important Features

  1. Real-Time Messaging: Users can exchange messages in real-time, enabling instant communication.
  2. User Authentication: Secure login and authentication mechanisms to ensure privacy and data protection.
  3. Contacts and Friends List: Ability to add, manage, and organize contacts or friends for easy messaging.
  4. Presence Status: Displaying the online/offline status of contacts to know their availability.
  5. Message Delivery and Read Receipts: Indicating the status of sent messages, such as delivered and read.
  6. Multimedia Sharing: Supporting the exchange of images, videos, and files alongside text messages.
  7. Push Notifications: Sending notifications to users for new messages or updates even when the app is not active.
  8. Emojis and Stickers: Allowing users to express emotions and add fun elements to their conversations.
  9. Group Chats: Enabling users to create and participate in group conversations with multiple participants.
  10. Message Search: Facilitating quick searching of past conversations for specific messages.
  11. End-to-End Encryption: Ensuring that messages are encrypted and secure from unauthorized access.

Scaling Requirements — Capacity Estimation

Let’s do a smaill scale simualtion for IM:

Scalability Requirements:

  • Total number of users: 1.2 Billion
  • Daily active users (DAU): 300 million
  • Average number of messages sent by a user per day: 10
  • Total number of messages sent per day: 3 Billion messages/day
  • Read-to-write ratio: 100:1

Storage Estimation:

  • Let’s assume on average each message size is 1KB
  • Total Storage per day: 3 Billion * 1KB = 3 TB/day
  • For the next 3 years: 3 TB * 5 * 365 = 5.475 PB

Requests per Second:

  • Messages sent per second: 3 Billion / (24 hours * 3600 seconds) ≈ 34,722 messages/second
class InstantMessenger:
    def __init__(self):
        self.users = {}
        self.messages = []

    def send_message(self, sender_id, receiver_id, content):
        # Check if both sender and receiver exist
        if sender_id not in self.users or receiver_id not in self.users:
            return "Invalid sender or receiver"

        # Create a new message and add it to the messages list
        message = {
            "sender_id": sender_id,
            "receiver_id": receiver_id,
            "content": content
        }
        self.messages.append(message)
        return "Message sent successfully"

    def add_user(self, user_id, username):
        # Add a new user to the system
        self.users[user_id] = {"user_id": user_id, "username": username}

    def get_user_messages(self, user_id):
        # Retrieve all messages for a given user
        user_messages = [message for message in self.messages if message['sender_id'] == user_id or message['receiver_id'] == user_id]
        return user_messages


if __name__ == '__main__':
    # Create an instance of the InstantMessenger
    im = InstantMessenger()

    # Add users to the system
    for user_id in range(1, 300001):  # Assuming user IDs start from 1 and go up to 300,000
        im.add_user(user_id, f"user_{user_id}")

    # Simulate message sending for a day
    for _ in range(10):  # Assume 10 iterations for 10 days
        for user_id in range(1, 300001):
            # Simulate sending 10 messages by each user
            for i in range(10):
                receiver_id = user_id + 1 if user_id < 300000 else 1  # Loop around users for simplicity
                message_content = f"Hello from user_{user_id}, message {i+1}"
                im.send_message(user_id, receiver_id, message_content)

    # Retrieve messages for a specific user (e.g., user with ID 1)
    user1_messages = im.get_user_messages(1)
    for message in user1_messages:
        print(f"From: user_{message['sender_id']} To: user_{message['receiver_id']} Content: {message['content']}")

Data Model — ER requirements

  1. User: Stores user details such as UserID, Username, Password, Email, etc.
  2. Contact/Friend: Represents the relationship between users, indicating who are contacts or friends.
  3. Message: Contains message details such as MessageID, Content, Timestamp, SenderID, ReceiverID, etc.
  4. Group: Stores information about group chats, including GroupID, GroupName, Members, etc.

High Level Design

  1. Horizontal Scalability: The system should be able to distribute the load across multiple servers to handle increased user traffic.
  2. Data Partitioning: Messages and user data should be partitioned to avoid hotspots and distribute the database load.
  3. Caching: Implementing caching mechanisms to reduce database queries and improve response times.
  4. Load Balancing: Using load balancers to distribute incoming requests evenly among multiple servers.
  5. Asynchronous Processing: Decoupling time-consuming tasks (e.g., message delivery) to be processed asynchronously.
  6. Client Application: Responsible for rendering the user interface, managing user interactions, and sending/receiving messages through APIs.
  7. API Gateway: Acts as an entry point for client requests, authenticates users, and forwards requests to appropriate services.
  8. User Service: Handles user-related operations such as user creation, authentication, and friend management.
  9. Message Service: Manages message-related operations like sending, receiving, and deleting messages.
  10. Group Service: Handles group chat operations, including group creation and member management.
  11. Push Notification Service: Sends push notifications to users for new messages or updates.
  12. WebSockets: Enables real-time bidirectional communication between the server and the client.
  13. Caching Service: Stores frequently accessed data to reduce database queries and improve performance.
  14. Mobile Client: Users will access the Instant Messenger platform through mobile applications.
  15. Application Servers: Responsible for handling read, write, and notification services. These servers manage user authentication, message sending, receiving, and processing various user actions.
  16. Load Balancer: Routes and directs incoming requests from mobile clients to the appropriate application servers based on load distribution.
  17. Cache (Memcache): Caches frequently accessed data, such as user details and recent messages, to reduce database queries and improve response times.
  18. Database: Stores user data, messages, contacts, and group information.

Main Components and Services

User Service:

  • User Registration: Allows users to register with a unique username, email, and password.
  • User Login: Authenticates users with their credentials and provides access to the Instant Messenger platform.
  • User Profile: Retrieves user details such as username, email, and other profile information.

Message Service:

  • Send Message: Enables users to send messages to other users or groups.
  • Receive Message: Delivers messages to the intended recipients and notifies them of new messages.
  • Message History: Retrieves the message history for a user or group.

Contact Service:

  • Add Contact: Allows users to add other users as contacts for easy messaging.
  • Remove Contact: Enables users to remove contacts from their contact list.

Group Service:

  • Create Group: Allows users to create new groups for group conversations.
  • Add/Remove Group Members: Enables users to add or remove members from a group.

Feed Generation Service:

  • Generates and curates the user’s feed, showing recent and relevant messages from contacts and groups.

Notification Service:

  • Sends push notifications to users for new messages, contact requests, and group invitations.

Search Service:

  • Facilitates quick searching of past conversations and users.

Encryption Service:

  • Ensures end-to-end encryption for messages to ensure data security and privacy.
class InstantMessenger:
    def __init__(self):
        self.users = {}
        self.messages = []
        self.contacts = {}
        self.groups = {}
        self.feed = {}

    # User Service
    def register_user(self, username, email, password):
        user_id = len(self.users) + 1
        user = {
            "user_id": user_id,
            "username": username,
            "email": email,
            "password": password
        }
        self.users[user_id] = user
        return user

    def login_user(self, username, password):
        for user in self.users.values():
            if user['username'] == username and user['password'] == password:
                return user
        return None

    def get_user_profile(self, user_id):
        return self.users.get(user_id, None)

    # Message Service
    def send_message(self, sender_id, receiver_id, content):
        message_id = len(self.messages) + 1
        message = {
            "message_id": message_id,
            "sender_id": sender_id,
            "receiver_id": receiver_id,
            "content": content
        }
        self.messages.append(message)
        self._notify_receiver(receiver_id, message)
        return message

    def _notify_receiver(self, receiver_id, message):
        # Simulating push notifications
        print(f"Notification: You have a new message from {message['sender_id']}")

    def get_user_messages(self, user_id):
        user_messages = [message for message in self.messages if message['sender_id'] == user_id or message['receiver_id'] == user_id]
        return user_messages

    # Contact Service
    def add_contact(self, user_id, contact_id):
        if user_id not in self.contacts:
            self.contacts[user_id] = set()
        self.contacts[user_id].add(contact_id)

    def remove_contact(self, user_id, contact_id):
        if user_id in self.contacts:
            self.contacts[user_id].discard(contact_id)

    # Group Service
    def create_group(self, group_name, user_ids):
        group_id = len(self.groups) + 1
        group = {
            "group_id": group_id,
            "group_name": group_name,
            "members": user_ids
        }
        self.groups[group_id] = group
        return group

    def add_member_to_group(self, group_id, user_id):
        if group_id in self.groups:
            self.groups[group_id]["members"].append(user_id)

    def remove_member_from_group(self, group_id, user_id):
        if group_id in self.groups:
            self.groups[group_id]["members"].remove(user_id)

    # Feed Generation Service
    def generate_feed(self, user_id):
        user_contacts = self.contacts.get(user_id, set())
        user_groups = [group for group in self.groups.values() if user_id in group["members"]]
        feed = self.get_user_messages(user_id)
        for contact_id in user_contacts:
            feed.extend(self.get_user_messages(contact_id))
        for group in user_groups:
            for member_id in group["members"]:
                if member_id != user_id:
                    feed.extend(self.get_user_messages(member_id))
        self.feed[user_id] = sorted(feed, key=lambda x: x['message_id'], reverse=True)[:50]

    def get_user_feed(self, user_id):
        return self.feed.get(user_id, [])

    # Notification Service
    def send_notification(self, user_id, notification):
        # Simulating push notifications
        print(f"Notification to User {user_id}: {notification}")

    # Search Service
    def search_messages(self, query):
        search_results = [message for message in self.messages if query in message['content']]
        return search_results

    def search_users(self, query):
        search_results = [user for user in self.users.values() if query in user['username']]
        return search_results

    # Encryption Service
    def encrypt_message(self, message_content):
        # Implement encryption logic here (e.g., using cryptography libraries)
        encrypted_content = "Encrypted: " + message_content
        return encrypted_content

    def decrypt_message(self, encrypted_content):
        # Implement decryption logic here (e.g., using cryptography libraries)
        decrypted_content = encrypted_content.replace("Encrypted: ", "")
        return decrypted_content


if __name__ == '__main__':
    im = InstantMessenger()

    # User Service
    user1 = im.register_user("user1", "[email protected]", "password1")
    user2 = im.register_user("user2", "[email protected]", "password2")

    user1 = im.login_user("user1", "password1")
    user2 = im.login_user("user2", "password2")

    user1_profile = im.get_user_profile(user1['user_id'])
    user2_profile = im.get_user_profile(user2['user_id'])

    # Message Service
    im.send_message(user1['user_id'], user2['user_id'], "Hello, User2!")
    im.send_message(user2['user_id'], user1['user_id'], "Hi, User1!")

    user1_messages = im.get_user_messages(user1['user_id'])
    user2_messages = im.get_user_messages(user2['user_id'])

    # Contact Service
    im.add_contact(user1['user_id'], user2['user_id'])
    im.remove_contact(user1['user_id'], user2['user_id'])

    # Group Service
    group1 = im.create_group("Family Group", [user1['user_id'], user2['user_id']])
    im.add_member_to_group(group1['group_id'], user1['user_id'])
    im.remove_member_from_group(group1['group_id'], user1['user_id'])

    # Feed Generation Service
    im.generate_feed(user1['user_id'])
    user1_feed = im.get_user_feed(user1['user_id'])

    # Notification Service
    im.send_notification(user2['user_id'], "You have a new message from User1!")

    # Search Service
    search_results = im.search_messages("Hello")

    # Encryption Service
    encrypted_message = im.encrypt_message("Hello, User2!")
    decrypted_message = im.decrypt_message(encrypted_message)

Basic Low Level Design

# Sample data to represent user and message storage (Replace this with a database in a real implementation)
users = {
    1: {"id": 1, "username": "user1", "password": "password1"},
    2: {"id": 2, "username": "user2", "password": "password2"},
    # Add more users as needed
}

messages = []


# Function to register a new user
def register_user(username, password):
    # Check if the user already exists
    for user in users.values():
        if user['username'] == username:
            return None, "Username already exists"

    # Generate a unique user ID
    user_id = max(users.keys()) + 1 if users else 1

    # Create a new user and store in the user dictionary
    user = {"id": user_id, "username": username, "password": password}
    users[user_id] = user

    return user, "User created successfully"


# Function to authenticate a user
def login_user(username, password):
    # Check if the user exists and the password is correct
    for user in users.values():
        if user['username'] == username and user['password'] == password:
            return user, "Login successful"

    return None, "Invalid username or password"


# Function to send a message
def send_message(sender_id, receiver_id, content):
    # Check if both sender and receiver exist
    if sender_id not in users or receiver_id not in users:
        return None, "Invalid sender or receiver"

    # Create a new message and add it to the messages list
    message = {
        "sender_id": sender_id,
        "receiver_id": receiver_id,
        "content": content
    }
    messages.append(message)

    return message, "Message sent successfully"


# Test the functions
if __name__ == '__main__':
    # Test user registration
    user1, msg1 = register_user("user1", "password1")
    print(msg1)  # Output: User created successfully

    user2, msg2 = register_user("user2", "password2")
    print(msg2)  # Output: User created successfully

    _, msg3 = register_user("user1", "password123")
    print(msg3)  # Output: Username already exists

    # Test user login
    _, login_msg1 = login_user("user1", "password1")
    print(login_msg1)  # Output: Login successful

    _, login_msg2 = login_user("user2", "password123")
    print(login_msg2)  # Output: Invalid username or password

    # Test sending a message
    message, send_msg = send_message(sender_id=user1['id'], receiver_id=user2['id'], content="Hello, User2!")
    print(send_msg)  # Output: Message sent successfully

API Design

User API:

  • /users/register (POST): Register a new user.
  • /users/login (POST): Authenticate a user.
  • /users/{user_id}/friends (GET): Get the list of user's friends/contacts.

Message API:

  • /messages/send (POST): Send a message to a user or group.
  • /messages/{message_id} (GET): Get details of a specific message.
  • /messages/search (GET): Search for messages based on content or timestamps.

Group API:

  • /groups/create (POST): Create a new group chat.
  • /groups/{group_id}/add_member (POST): Add a user to a group.
  • /groups/{group_id}/remove_member (POST): Remove a user from a group.

Push Notification API:

  • /notifications/register (POST): Register a device for push notifications.
  • /notifications/unregister (POST): Unregister a device from push notifications.
from flask import Flask, request

app = Flask(__name__)
instant_messenger = InstantMessenger()

# User Registration API
@app.route("/users/register", methods=["POST"])
def register_user():
    data = request.json
    user_id = str(len(instant_messenger.users) + 1)
    username = data.get("username")
    password = data.get("password")
    user = User(user_id, username, password)
    instant_messenger.add_user(user)
    return {
        "user_id": user_id,
        "username": username,
    }, 201

# Send Message API
@app.route("/messages/send", methods=["POST"])
def send_message():
    data = request.json
    sender_id = data.get("sender_id")
    receiver_id = data.get("receiver_id")
    content = data.get("content")
    message = instant_messenger.send_message(sender_id, receiver_id, content)
    if message:
        return {
            "message_id": message.message_id,
            "sender": message.sender.username,
            "receiver": message.receiver.username,
            "content": message.content,
        }, 200
    else:
        return {"message": "User not found"}, 404

# Get Messages API
@app.route("/messages/get/<user_id>", methods=["GET"])
def get_user_messages(user_id):
    user_messages = instant_messenger.get_user_messages(user_id)
    if user_messages:
        messages_data = []
        for message in user_messages:
            messages_data.append({
                "message_id": message.message_id,
                "sender": message.sender.username,
                "receiver": message.receiver.username,
                "content": message.content,
            })
        return {"messages": messages_data}, 200
    else:
        return {"message": "User not found or no messages found"}, 404

# Run the Flask app
if __name__ == "__main__":
    app.run()

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

# Real-Time Messaging
class InstantMessenger:
    def __init__(self):
        self.users = {}
        self.messages = []

    def send_message(self, sender_id, receiver_id, content):
        # Check if both sender and receiver exist
        if sender_id not in self.users or receiver_id not in self.users:
            return "Invalid sender or receiver"

        # Create a new message and add it to the messages list
        message = {
            "sender_id": sender_id,
            "receiver_id": receiver_id,
            "content": content
        }
        self.messages.append(message)
        return "Message sent successfully"


# User Authentication
def login_user(username, password, users):
    # Check if the user exists and the password is correct
    for user_id, user in users.items():
        if user['username'] == username and user['password'] == password:
            return user_id, "Login successful"

    return None, "Invalid username or password"


# Contacts and Friends List
def add_contact(user_id, contact_id, contacts):
    # Check if the user exists
    if user_id not in contacts:
        return "Invalid user"

    # Add the contact
    contacts[user_id].add(contact_id)
    return "Contact added successfully"


# Presence Status
def set_presence_status(user_id, status, presence_status):
    presence_status[user_id] = status
    return "Presence status updated successfully"


# Message Delivery and Read Receipts
def mark_message_delivered(message_id, delivered_status, messages):
    # Check if the message exists
    for message in messages:
        if message['message_id'] == message_id:
            message['delivered'] = delivered_status
            return "Message delivery status updated successfully"

    return "Invalid message ID"


def mark_message_read(message_id, read_status, messages):
    # Check if the message exists
    for message in messages:
        if message['message_id'] == message_id:
            message['read'] = read_status
            return "Message read status updated successfully"

    return "Invalid message ID"


# Multimedia Sharing
def share_multimedia(sender_id, receiver_id, content, media_type, messages):
    # Check if both sender and receiver exist
    if sender_id not in self.users or receiver_id not in self.users:
        return "Invalid sender or receiver"

    # Create a new message and add it to the messages list
    message = {
        "sender_id": sender_id,
        "receiver_id": receiver_id,
        "content": content,
        "media_type": media_type
    }
    messages.append(message)
    return "Multimedia shared successfully"


# Push Notifications
def send_push_notification(user_id, notification, push_notifications):
    push_notifications[user_id] = notification
    return "Push notification sent successfully"


# Emojis and Stickers
def add_emoji_sticker(message_id, emoji_sticker, messages):
    # Check if the message exists
    for message in messages:
        if message['message_id'] == message_id:
            if 'emojis_stickers' not in message:
                message['emojis_stickers'] = []
            message['emojis_stickers'].append(emoji_sticker)
            return "Emoji/Sticker added successfully"

    return "Invalid message ID"


# Group Chats
def create_group(group_name, members, groups):
    # Generate a unique group ID
    group_id = max(groups.keys()) + 1 if groups else 1

    # Create the group and add it to the groups dictionary
    group = {"group_id": group_id, "group_name": group_name, "members": members}
    groups[group_id] = group
    return "Group created successfully"


def add_member_to_group(group_id, member_id, groups):
    # Check if the group exists
    if group_id not in groups:
        return "Invalid group ID"

    # Add the member to the group
    groups[group_id]["members"].append(member_id)
    return "Member added to the group successfully"


# Message Search
def search_messages(query, messages):
    # Search for messages based on content or timestamps
    search_results = []
    for message in messages:
        if query in message['content']:
            search_results.append(message)

    return search_results


# End-to-End Encryption
def encrypt_message(message_content):
    # Implement encryption logic here (e.g., using cryptography libraries)
    encrypted_content = "Encrypted: " + message_content
    return encrypted_content


def decrypt_message(encrypted_content):
    # Implement decryption logic here (e.g., using cryptography libraries)
    decrypted_content = encrypted_content.replace("Encrypted: ", "")
    return decrypted_content


if __name__ == '__main__':
    # Usage example
    im = InstantMessenger()
    im.users = {
        1: {"username": "user1", "password": "password1"},
        2: {"username": "user2", "password": "password2"},
    }

    im.send_message(1, 2, "Hello, User2!")  # Output: "Message sent successfully"

    im.set_presence_status(1, "online")  # Output: "Presence status updated successfully"
    im.add_contact(1, 2)  # Output: "Contact added successfully"

    im.messages = [
        {"message_id": 1, "sender_id": 1, "receiver_id": 2, "content": "Hello, User2!", "delivered": True, "read": False},
    ]

    mark_message_delivered(1, True)  # Output: "Message delivery status updated successfully"
    mark_message_read(1, True)  # Output: "Message read status updated successfully"

    share_multimedia(1, 2, "cat.jpg", "image")  # Output: "Multimedia shared successfully"

    send_push_notification(2, "You have a new message from User1!")  # Output: "Push notification sent successfully"

    add_emoji_sticker(1, "🙂")  # Output: "Emoji/Sticker added successfully"

    groups = {}
    create_group("Family Group", [1, 2], groups)  # Output: "Group created successfully"
    add_member_to_group(1, 3, groups)  # Output: "Member added to the group successfully"

    search_results = search_messages("Hello", im.messages)  # Output: [{'message_id': 1, 'sender_id': 1, 'receiver_id': 2, 'content': 'Hello, User2!', 'delivered': True, 'read': False}]
    
    encrypted_message = encrypt_message("Hello, User2!")  # Output: Encrypted message using encryption logic
    decrypted_message = decrypt_message(encrypted_message)  # Output: "Hello, User2!"

System Design — Hacker News

We will be discussing in depth -

Pic credits : Pinterest

What is Hacker News

Hacker News is a social news website that focuses on computer science, entrepreneurship, and technology-related topics. It was created by Paul Graham, the co-founder of Y Combinator, and is popular among developers, entrepreneurs, and tech enthusiasts. Users can submit links to interesting articles, ask questions, and participate in discussions by upvoting and commenting on posts.

Important Features

  • User Registration and Authentication: Users can create accounts and log in to participate in discussions and engage with the community.
  • Post Submission: Users can submit links to articles or ask questions, which will be visible to other users on the platform.
  • Voting System: Users can upvote or downvote posts and comments, which influences the visibility and ranking of the content.
  • Commenting System: Users can comment on posts and reply to other comments, promoting discussions and interactions.
  • Moderation: Implementing moderation features to control spam and maintain the quality of content.
  • User Profiles: Each user has a profile that showcases their submitted posts, comments, and voting history.
  • Real-time Updates: Users should see new posts, comments, and votes in real-time without the need for manual refreshing.

Scaling Requirements — Capacity Estimation

Small scale Simulation for Hacker News:

Assumptions:

  • Total number of users: 10 Million
  • Daily active users (DAU): 2 Million
  • Number of posts viewed by a user/day: 5
  • Total number of posts viewed per day: 10 Million posts/day
  • Since the system is read-heavy, let’s assume the read-to-write ratio to be 50:1.
  • Total number of posts submitted/day = 1/50 * 10 Million = 200,000 posts/day

Storage estimation:

  • Average size of a post: 10 KB
  • Total Storage per day: 200,000 * 10 KB = 2,000,000 KB = 1.86 GB/day
  • For the next 3 years: 1.86 GB * 365 days * 3 years ≈ 2.04 TB
  • Requests per second: 10 Million / 3600 seconds * 24 hours ≈ 120 requests/second

Data Model — ER requirements

  • User: Stores user details like username, email, password, etc.
  • Post: Represents each submitted link/article with metadata like title, URL, timestamp, and vote count.
  • Comment: Stores comments made by users on posts, with references to the parent post and user who made the comment.
  • Vote: Records votes made by users on posts and comments.
User

ID (Primary Key)
Username (Unique)
Email (Unique)
Password
Registration Date
Last Login Date

Post

ID (Primary Key)
Title
Content
AuthorID (Foreign Key referencing User.ID)
Creation Timestamp
Last Updated Timestamp

Comment

ID (Primary Key)
PostID (Foreign Key referencing Post.ID)
Parent Comment ID (Foreign Key referencing Comment.ID, for replies)
AuthorID (Foreign Key referencing User.ID)
Content
Creation Timestamp
Last Updated Timestamp

Vote

ID (Primary Key)
UserID (Foreign Key referencing User.ID)
Target Type (Post or Comment)
Target ID (Foreign Key referencing Post.ID or Comment.ID)
Vote Type (Upvote or Downvote)
Creation Timestamp

High Level Design

  • Web Servers: Responsible for handling incoming HTTP requests from users’ browsers and serving HTML pages.
  • Application Servers: Process the business logic, handle authentication, and interact with the database.
  • Database Servers: Store user data, posts, comments, votes, etc.
  • Caching Layer: Stores frequently accessed data to reduce database load.
  • Content Delivery Network (CDN): Serves static content like images, CSS, and JavaScript for faster delivery.
  • Background Workers: Perform asynchronous tasks such as sending emails and processing notifications.
  • Load Balancing: Distributing incoming traffic across multiple servers to prevent overload on any one server.
  • Caching: Implementing caching mechanisms to reduce database and server load.
  • Database Scaling: Utilizing sharding, partitioning, or NoSQL solutions to handle increasing amounts of data.
  • Content Delivery Network (CDN): Using a CDN to serve static assets and reduce latency for users across the globe.
  • Asynchronous Processing: Offloading resource-intensive tasks to background workers to maintain responsiveness.

Assumptions:

  • There will be more reads than writes, so the system is read-heavy.
  • Users should have real-time updates on posts and comments.
  • The system needs to be highly available and scalable to handle millions of users.

Main Components:

  1. Web Servers: Handle incoming HTTP requests from users’ browsers.
  2. Application Servers: Perform business logic, handle authentication, and process user requests.
  3. Database Servers: Store user data, posts, comments, and votes.
  4. Cache Servers: Cache frequently accessed data to reduce database load.
  5. Load Balancer: Distributes incoming traffic across multiple servers to ensure even distribution.
  6. Content Delivery Network (CDN): Serves static assets for faster delivery to users across the globe.

Services for Hacker News System:

User Service:

  • Register User: Allows users to create accounts and store user information in the database.
  • Login/Authentication: Handles user login and authentication using secure mechanisms.
  • User Profile: Fetches and displays user profiles with their submitted posts, comments, and voting history.

Post Service:

  • Create Post: Allows users to submit new posts and store post information in the database.
  • View Post: Retrieves and displays posts with comments, votes, and author information.
  • Update Post: Enables users to edit and update their posts.

Comment Service:

  • Add Comment: Allows users to comment on posts and store comment information in the database.
  • Reply to Comment: Allows users to reply to existing comments and store the reply information.

Vote Service:

  • Upvote/Downvote Post: Allows users to upvote or downvote posts and store vote information.
  • Upvote/Downvote Comment: Allows users to upvote or downvote comments and store vote information.

Feed Generation Service:

  • Generates personalized news feeds for users based on the posts of users they follow.
  • Utilizes ranking algorithms to prioritize relevant, popular, and recent posts.

Real-time Updates Service:

  • Provides real-time updates to users for new posts, comments, and votes.
  • Utilizes WebSockets or similar technologies to push updates instantly.

Moderation Service:

  • Implements moderation features to control spam, offensive content, and maintain content quality.

Basic Low Level Design

User Entity:

  • userId: Unique identifier for each user.
  • username: User’s username.
  • password: User’s password.
  • otherUserAttributes: Any other attributes related to the user, e.g., email, registration date, etc.

Post Entity:

  • postId: Unique identifier for each post.
  • user: Reference to the User entity, representing the author of the post.
  • caption: The caption or text associated with the post.
  • otherPostAttributes: Any other attributes related to the post, e.g., creation timestamp, likes count, etc.

Comment Entity:

  • commentId: Unique identifier for each comment.
  • post: Reference to the Post entity that the comment belongs to.
  • user: Reference to the User entity, representing the author of the comment.
  • content: The content or text of the comment.
  • otherCommentAttributes: Any other attributes related to the comment, e.g., creation timestamp, likes count, etc.
from flask import Flask, request, jsonify

app = Flask(__name__)

# Dummy in-memory data storage (simplified for demonstration)
users = []
posts = []
comments = []
votes = []

# User Service
def register_user(username, email, password):
    new_user = {'username': username, 'email': email, 'password': password, 'posts': [], 'comments': []}
    users.append(new_user)
    return new_user

def get_user_by_username(username):
    for user in users:
        if user['username'] == username:
            return user
    return None

@app.route('/api/register', methods=['POST'])
def api_register_user():
    data = request.json
    username = data.get('username')
    email = data.get('email')
    password = data.get('password')

    if not username or not email or not password:
        return jsonify({'error': 'All fields are required.'}), 400

    if get_user_by_username(username):
        return jsonify({'error': 'Username already exists.'}), 409

    new_user = register_user(username, email, password)
    return jsonify({'message': 'Registration successful.', 'user': new_user}), 201

# Post Service
def create_post(author_id, title, content):
    new_post = {'title': title, 'content': content, 'author_id': author_id, 'comments': []}
    posts.append(new_post)
    user = get_user_by_id(author_id)
    user['posts'].append(new_post)
    return new_post

def get_post_by_id(post_id):
    for post in posts:
        if post['id'] == post_id:
            return post
    return None

@app.route('/api/posts', methods=['POST'])
def api_create_post():
    data = request.json
    author_id = data.get('author_id')
    title = data.get('title')
    content = data.get('content')

    if not author_id or not title or not content:
        return jsonify({'error': 'Author ID, title, and content are required.'}), 400

    user = get_user_by_id(author_id)
    if not user:
        return jsonify({'error': 'User not found.'}), 404

    new_post = create_post(author_id, title, content)
    return jsonify({'message': 'Post created successfully.', 'post': new_post}), 201

# Comment Service
def add_comment(post_id, author_id, content):
    post = get_post_by_id(post_id)
    if not post:
        return None

    new_comment = {'post_id': post_id, 'author_id': author_id, 'content': content}
    comments.append(new_comment)
    post['comments'].append(new_comment)

    return new_comment

def get_comment_by_id(comment_id):
    for comment in comments:
        if comment['id'] == comment_id:
            return comment
    return None

@app.route('/api/comments', methods=['POST'])
def api_add_comment():
    data = request.json
    post_id = data.get('post_id')
    author_id = data.get('author_id')
    content = data.get('content')

    if not post_id or not author_id or not content:
        return jsonify({'error': 'Post ID, author ID, and content are required.'}), 400

    post = get_post_by_id(post_id)
    if not post:
        return jsonify({'error': 'Post not found.'}), 404

    user = get_user_by_id(author_id)
    if not user:
        return jsonify({'error': 'User not found.'}), 404

    new_comment = add_comment(post_id, author_id, content)
    if not new_comment:
        return jsonify({'error': 'Failed to add comment.'}), 500

    return jsonify({'message': 'Comment added successfully.', 'comment': new_comment}), 201

# Vote Service
def vote(voter_id, target_type, target_id, vote_type):
    new_vote = {'voter_id': voter_id, 'target_type': target_type, 'target_id': target_id, 'vote_type': vote_type}
    votes.append(new_vote)
    return new_vote

@app.route('/api/votes', methods=['POST'])
def api_vote():
    data = request.json
    voter_id = data.get('voter_id')
    target_type = data.get('target_type')
    target_id = data.get('target_id')
    vote_type = data.get('vote_type')

    if not voter_id or not target_type or not target_id or not vote_type:
        return jsonify({'error': 'Voter ID, target type, target ID, and vote type are required.'}), 400

    new_vote = vote(voter_id, target_type, target_id, vote_type)
    return jsonify({'message': 'Vote recorded successfully.', 'vote': new_vote}), 201

if __name__ == '__main__':
    app.run()

API Design

  • User API: Endpoints for user registration, authentication, and profile management.
  • Post API: Endpoints for submitting, retrieving, and voting on posts.
  • Comment API: Endpoints for commenting on posts and replying to comments.
  • Moderation API: Endpoints for moderation actions, such as flagging or reporting content.
  • Real-time API: Implement WebSocket or similar technology for real-time updates.
from flask import Flask, Blueprint, request, jsonify

app = Flask(__name__)
user_api = Blueprint('user_api', __name__)
post_api = Blueprint('post_api', __name__)

# In-memory data storage
users = []
posts = []

# Helper function to find a user by their username
def find_user_by_username(username):
    for user in users:
        if user['username'] == username:
            return user
    return None

@user_api.route('/register', methods=['POST'])
def register_user():
    data = request.json
    username = data.get('username')
    email = data.get('email')
    password = data.get('password')

    # Basic input validation
    if not username or not email or not password:
        return jsonify({'error': 'All fields are required.'}), 400

    # Check if the username already exists
    if find_user_by_username(username):
        return jsonify({'error': 'Username already exists.'}), 409

    # Create a new user
    new_user = {'username': username, 'email': email, 'password': password}
    users.append(new_user)

    return jsonify({'message': 'Registration successful.'}), 201

@post_api.route('/submit', methods=['POST'])
def submit_post():
    data = request.json
    title = data.get('title')
    url = data.get('url')
    username = data.get('username')  # In a real-world scenario, this would be obtained from user authentication.

    # Basic input validation
    if not title or not url or not username:
        return jsonify({'error': 'Title, URL, and username are required.'}), 400

    # Check if the user exists
    user = find_user_by_username(username)
    if not user:
        return jsonify({'error': 'User not found.'}), 404

    # Create a new post
    new_post = {'title': title, 'url': url, 'username': username, 'votes': 0}
    posts.append(new_post)

    return jsonify({'message': 'Post submitted successfully.'}), 201

@post_api.route('/vote', methods=['POST'])
def vote_post():
    data = request.json
    post_title = data.get('post_title')
    username = data.get('username')  # In a real-world scenario, this would be obtained from user authentication.
    vote_type = data.get('vote_type')  # 'upvote' or 'downvote'

    # Basic input validation
    if not post_title or not username or vote_type not in ['upvote', 'downvote']:
        return jsonify({'error': 'Invalid input data.'}), 400

    # Find the post
    for post in posts:
        if post['title'] == post_title:
            # Check if the user exists
            user = find_user_by_username(username)
            if not user:
                return jsonify({'error': 'User not found.'}), 404

            # Upvote or downvote the post
            if vote_type == 'upvote':
                post['votes'] += 1
            else:
                post['votes'] -= 1

            return jsonify({'message': 'Vote recorded successfully.'}), 200

    return jsonify({'error': 'Post not found.'}), 404

if __name__ == '__main__':
    app.register_blueprint(user_api, url_prefix='/api/users')
    app.register_blueprint(post_api, url_prefix='/api/posts')
    app.run()

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

from flask import Flask, request, jsonify

app = Flask(__name__)

# In-memory data storage (simplified for demonstration)
users = []
posts = []
comments = []

# User Registration and Authentication
@app.route('/api/register', methods=['POST'])
def register_user():
    data = request.json
    username = data.get('username')
    password = data.get('password')

    # Basic input validation
    if not username or not password:
        return jsonify({'error': 'All fields are required.'}), 400

    # Check if the username already exists
    for user in users:
        if user['username'] == username:
            return jsonify({'error': 'Username already exists.'}), 409

    new_user = {'username': username, 'password': password, 'posts': [], 'comments': [], 'votes': {}}
    users.append(new_user)

    return jsonify({'message': 'Registration successful.'}), 201

# Post Submission
@app.route('/api/submit_post', methods=['POST'])
def submit_post():
    data = request.json
    title = data.get('title')
    content = data.get('content')
    username = data.get('username')

    # Basic input validation
    if not title or not content or not username:
        return jsonify({'error': 'Title, content, and username are required.'}), 400

    # Find the user
    user = None
    for u in users:
        if u['username'] == username:
            user = u
            break

    if not user:
        return jsonify({'error': 'User not found.'}), 404

    new_post = {'title': title, 'content': content, 'author': username, 'votes': 0, 'comments': []}
    posts.append(new_post)
    user['posts'].append(new_post)

    return jsonify({'message': 'Post submitted successfully.'}), 201

# Voting System
@app.route('/api/vote', methods=['POST'])
def vote_post():
    data = request.json
    post_id = data.get('post_id')
    username = data.get('username')
    vote_type = data.get('vote_type')  # 'upvote' or 'downvote'

    # Basic input validation
    if not post_id or not username or vote_type not in ['upvote', 'downvote']:
        return jsonify({'error': 'Invalid input data.'}), 400

    # Find the post
    post = None
    for p in posts:
        if p['id'] == post_id:
            post = p
            break

    if not post:
        return jsonify({'error': 'Post not found.'}), 404

    # Find the user
    user = None
    for u in users:
        if u['username'] == username:
            user = u
            break

    if not user:
        return jsonify({'error': 'User not found.'}), 404

    # Apply the vote to the post
    if vote_type == 'upvote':
        post['votes'] += 1
    else:
        post['votes'] -= 1

    # Store the vote in the user's vote history
    user['votes'][post_id] = vote_type

    return jsonify({'message': 'Vote recorded successfully.'}), 200

# Commenting System
@app.route('/api/comment', methods=['POST'])
def add_comment():
    data = request.json
    post_id = data.get('post_id')
    username = data.get('username')
    content = data.get('content')

    # Basic input validation
    if not post_id or not username or not content:
        return jsonify({'error': 'Post ID, username, and content are required.'}), 400

    # Find the post
    post = None
    for p in posts:
        if p['id'] == post_id:
            post = p
            break

    if not post:
        return jsonify({'error': 'Post not found.'}), 404

    # Find the user
    user = None
    for u in users:
        if u['username'] == username:
            user = u
            break

    if not user:
        return jsonify({'error': 'User not found.'}), 404

    new_comment = {'content': content, 'author': username, 'votes': 0}
    comments.append(new_comment)
    post['comments'].append(new_comment)
    user['comments'].append(new_comment)

    return jsonify({'message': 'Comment added successfully.'}), 201

# Moderation (not implemented in this simplified version)

# User Profiles
@app.route('/api/user_profile/<username>', methods=['GET'])
def get_user_profile(username):
    # Find the user
    user = None
    for u in users:
        if u['username'] == username:
            user = u
            break

    if not user:
        return jsonify({'error': 'User not found.'}), 404

    return jsonify(user)

# Real-time Updates (not implemented in this simplified version)

if __name__ == '__main__':
    app.run()

System Design — Facebook Timeline Function

We will be discussing in depth -

Pic credits : Pinterest

What is Facebook Timeline Function

Facebook Timeline is a feature that allows users to create a chronological profile of their life events, activities, and shared content on the Facebook platform. It presents a personalized history of a user’s posts, photos, videos, and other interactions, providing an engaging way for users to reminisce and share their life journey with friends and followers.

Important Features

  1. Chronological Ordering: Facebook Timeline displays content in reverse-chronological order, showing the most recent events first.
  2. Multimedia Content: Users can add various types of media to their timeline, including photos, videos, and shared posts.
  3. Life Events: Users can highlight significant life events, such as birthdays, graduations, new jobs, and relationships.
  4. Privacy Controls: Facebook Timeline offers privacy settings that allow users to control who can view specific posts and events on their timeline.
  5. Activity Log: Users can review and manage all their past activities on Facebook through the activity log, ensuring transparency and control over their data.
  6. Featured Posts: The ability to pin or feature important posts or life events to make them more prominent on the timeline.

Scaling Requirements — Capacity Estimation

For the sake of simplicity, I’ll consider a smaller user base:

  • Total number of users: 100,000
  • Daily active users (DAU): 30,000
  • Number of posts by user/day: 5
  • Total number of posts per day: 150,000 posts/day

Since the system is read-heavy, let’s assume the read-to-write ratio is 50:1.

  • Total number of posts read per day: 150,000 * 50 = 7,500,000 reads/day
  • Total number of posts written per day: 150,000 writes/day

Let’s estimate the storage:

  • On average, each post size is 1 MB.
  • Total storage per day: 150,000 * 1 MB = 150 GB/day
  • For the next 3 years: 150 GB * 365 * 3 = 164.25 TB

Requests per second:

  • Posts read per second: 7,500,000 / (3600 seconds * 24 hours) ≈ 87 requests/second
  • Posts written per second: 150,000 / (3600 seconds * 24 hours) ≈ 2 requests/second
import random
from datetime import datetime, timedelta

class FacebookTimeline:
    def __init__(self):
        self.posts = {}

    def add_post(self, user_id, content):
        if user_id not in self.posts:
            self.posts[user_id] = []
        post = {
            "post_id": len(self.posts[user_id]) + 1,
            "content": content,
            "timestamp": datetime.now()
        }
        self.posts[user_id].append(post)

    def get_timeline(self, user_id):
        if user_id in self.posts:
            return sorted(self.posts[user_id], key=lambda x: x["timestamp"], reverse=True)
        return []

if __name__ == "__main__":
    facebook = FacebookTimeline()
    users = [f"user{i}" for i in range(1, 100001)]

    # Simulating daily activity
    for _ in range(30_000):
        user_id = random.choice(users)
        num_posts = random.randint(1, 5)
        for _ in range(num_posts):
            content = f"This is post {random.randint(1, 1000)} by {user_id}"
            facebook.add_post(user_id, content)

    # Get timeline for a random user
    user_id = random.choice(users)
    timeline = facebook.get_timeline(user_id)
    print(f"Timeline for user {user_id}:")
    for post in timeline:
        print(f"Post {post['post_id']}: {post['content']} ({post['timestamp']})")

Data Model — ER requirements

  1. User: Represents registered users with attributes like UserID, Name, Email, PasswordHash, etc.
  2. Timeline: Each user has a corresponding Timeline with attributes like TimelineID, UserID (foreign key), CreationDate, LastUpdateDate, etc.
  3. Posts: Represents individual posts with attributes like PostID, UserID (foreign key), Content, MediaType, PostDate, etc.
  4. LifeEvents: Stores user life events with attributes like EventID, UserID (foreign key), EventType, EventDate, Description, etc.
User:

userId (unique identifier for users)
username (user's display name)
email (user's email address)
password (user's password)
other attributes (e.g., profile picture, bio, etc.)

Post:

postId (unique identifier for posts)
userId (foreign key from the User table to identify the post owner)
content (text or media content of the post)
timestamp (timestamp indicating when the post was created)
other attributes (e.g., location, likes count, comments count, etc.)

Follow:

followerId (foreign key from the User table to identify the follower)
followeeId (foreign key from the User table to identify the user being followed)

Like:

likeId (unique identifier for likes)
userId (foreign key from the User table to identify the user who liked the post)
postId (foreign key from the Post table to identify the post that was liked)
timestamp (timestamp indicating when the like was added)

Comment:

commentId (unique identifier for comments)
userId (foreign key from the User table to identify the user who commented)
postId (foreign key from the Post table to identify the post on which the comment was made)
content (text content of the comment)
timestamp (timestamp indicating when the comment was added)

High Level Design

  1. High User Traffic: Facebook has billions of active users, so the system must handle a massive number of concurrent requests.
  2. Storage: As users add multimedia content to their timelines, the system needs to handle and efficiently store large amounts of data.
  3. High Availability: The Timeline should be accessible and responsive at all times, even during peak usage.
  4. Data Consistency: Ensuring consistency across distributed servers is crucial to maintaining accurate timelines.
  5. Frontend: Responsible for user interactions, rendering the timeline UI, and making API calls to the backend.
  6. Web Servers: Handle user requests from the frontend, perform authentication, and route requests to appropriate backend services.
  7. Load Balancer: Distributes incoming requests across multiple web servers to ensure optimal utilization and availability.
  8. Backend Services: Consist of various microservices, including User Service, Timeline Service, Post Service, Life Event Service, etc.
  9. Database Servers: Store user data, posts, and timeline information in a distributed and scalable database.
  10. Caching Layer: Employ caching mechanisms to reduce database load and improve response times for frequently accessed content.

Assumptions:

  • The system is read-heavy, as users spend more time viewing posts than creating them.
  • There will be more reads than writes, so we need a read-heavy system with more replicas for read operations.
  • Horizontal scaling will be used for handling increased traffic.
  • Services should be highly available.
  • Latency should be low for an optimal user experience.
  • Consistency is essential for ensuring users see the latest content.
  • Caching mechanisms will be used to reduce database load and improve response times.

Main Components and Services:

  1. Mobile Client: Represents users accessing the Facebook Timeline platform through mobile devices.
  2. Application Servers: Handle read, write, and notification requests from the mobile clients.
  3. Load Balancer: Routes and directs incoming requests to the appropriate servers based on designated services.
  4. Cache (Memcache or Redis): Used to cache frequently accessed data and reduce database load.
  5. CDN: Improves latency and throughput by caching and serving static content like images.
  6. Database: Stores user data, posts, likes, and comments.

Services:

User Service:

  • Register new users with a unique UserID.
  • Authenticate user login using email and password.

Post Service:

  • Allow users to create new posts and associate them with their UserID.
  • Retrieve posts for a user’s timeline based on their UserID.
  • Support post updates and deletions.

Like Service:

  • Allow users to like posts and store their UserID and the PostID they liked.
  • Provide functionality to unlike a post if required.

Comment Service:

  • Allow users to add comments to posts and store the CommentID, UserID, PostID, and comment text.
  • Support comment replies and nested comments.

Follow Service:

  • Enable users to follow other users by storing their UserID and the UserID they are following.

Feed Generation Service:

  • Generate the user’s timeline feed by fetching recent posts from users they follow.
  • Sort and rank posts based on activity (likes, comments) to provide a relevant and engaging feed.

Basic Low Level Design

import random
from datetime import datetime, timedelta

class FacebookTimeline:
    def __init__(self):
        self.users = {}
        self.posts = {}
        self.likes = {}
        self.comments = {}

    def add_user(self, user_id, username, email, password):
        self.users[user_id] = {
            "username": username,
            "email": email,
            "password": password
        }

    def create_post(self, user_id, content):
        if user_id not in self.posts:
            self.posts[user_id] = []
        post_id = len(self.posts[user_id]) + 1
        timestamp = datetime.now()
        post = {
            "post_id": post_id,
            "user_id": user_id,
            "content": content,
            "timestamp": timestamp
        }
        self.posts[user_id].append(post)
        return post_id

    def like_post(self, user_id, post_id):
        if post_id not in self.likes:
            self.likes[post_id] = []
        self.likes[post_id].append(user_id)

    def get_timeline(self, user_id):
        timeline = []
        for user in self.users.values():
            if user_id != user["user_id"]:
                for post in self.posts.get(user["user_id"], []):
                    timeline.append(post)
        timeline.sort(key=lambda x: x["timestamp"], reverse=True)
        return timeline

    def add_comment(self, user_id, post_id, text):
        if post_id not in self.comments:
            self.comments[post_id] = []
        comment_id = len(self.comments[post_id]) + 1
        timestamp = datetime.now()
        comment = {
            "comment_id": comment_id,
            "post_id": post_id,
            "user_id": user_id,
            "text": text,
            "timestamp": timestamp
        }
        self.comments[post_id].append(comment)
        return comment_id

    def get_comments(self, post_id):
        return self.comments.get(post_id, [])

# Example usage:
timeline = FacebookTimeline()

# Create users
timeline.add_user(1, "user1", "[email protected]", "password1")
timeline.add_user(2, "user2", "[email protected]", "password2")
timeline.add_user(3, "user3", "[email protected]", "password3")

# User1 creates a post
post_id1 = timeline.create_post(1, "This is post 1 by user1")

# User2 likes the post
timeline.like_post(2, post_id1)

# User2 adds a comment
timeline.add_comment(2, post_id1, "This is a comment by user2 on post 1")

# User3 adds a comment
timeline.add_comment(3, post_id1, "This is a comment by user3 on post 1")

# Get User1's timeline
user1_timeline = timeline.get_timeline(1)
print(f"User1's Timeline:")
for post in user1_timeline:
    print(f"Post {post['post_id']}: {post['content']} ({post['timestamp']})")
    comments = timeline.get_comments(post['post_id'])
    for comment in comments:
        print(f"  Comment {comment['comment_id']}: {comment['text']} ({comment['timestamp']})")

API Design

  1. POST /api/user/register: Register a new user.
  2. POST /api/user/login: Authenticate user login.
  3. GET /api/user/{userID}/timeline: Retrieve a user's timeline.
  4. POST /api/user/{userID}/post: Add a new post to the user's timeline.
  5. PUT /api/user/{userID}/post/{postID}: Update an existing post.
  6. DELETE /api/user/{userID}/post/{postID}: Delete a post from the timeline.

User Service API:

1. POST /api/user/register:

Request:

{
  "name": "John Doe",
  "email": "[email protected]",
  "password": "strong_password"
}

Response (Success):

{
  "userID": "user123",
  "name": "John Doe",
  "email": "[email protected]",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... (JWT token)"
}

Response (Error):

{
  "error": "User with this email already exists."
}

2. POST /api/user/login:

Request:

{
  "email": "[email protected]",
  "password": "strong_password"
}

Response (Success):

{
  "userID": "user123",
  "name": "John Doe",
  "email": "[email protected]",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... (JWT token)"
}

Response (Error):

{
  "error": "Invalid credentials. Please try again."
}

Timeline Service API:

1. GET /api/user/{userID}/timeline:

Response (Success):

{
  "userID": "user123",
  "name": "John Doe",
  "timeline": [
    {
      "postID": "post1",
      "content": "Had a great day at the beach!",
      "postDate": "2023-07-20T12:30:00",
      "mediaType": "photo",
      "mediaURL": "https://example.com/image123.jpg"
    },
    {
      "postID": "post2",
      "content": "Excited about the new project.",
      "postDate": "2023-07-19T14:45:00",
      "mediaType": "text"
    }
  ]
}

2. POST /api/user/{userID}/post:

Request:

{
  "content": "Enjoying a delicious meal.",
  "mediaType": "photo",
  "mediaURL": "https://example.com/image456.jpg"
}

Response (Success):

{
  "postID": "post3",
  "content": "Enjoying a delicious meal.",
  "postDate": "2023-07-21T09:15:00",
  "mediaType": "photo",
  "mediaURL": "https://example.com/image456.jpg"
}

3. PUT /api/user/{userID}/post/{postID}:

Request:

{
  "content": "Enjoying a delicious meal with friends.",
  "mediaType": "photo",
  "mediaURL": "https://example.com/image456.jpg"
}

Response (Success):

{
  "postID": "post3",
  "content": "Enjoying a delicious meal with friends.",
  "postDate": "2023-07-21T09:15:00",
  "mediaType": "photo",
  "mediaURL": "https://example.com/image456.jpg"
}

Response (Error):

{
  "error": "You are not authorized to edit this post."
}

4. DELETE /api/user/{userID}/post/{postID}:

Response (Success):

{
  "message": "Post with ID post3 has been deleted."
}

Response (Error):

{
  "error": "You are not authorized to delete this post."
}

User Service API:

from flask import Flask, request, jsonify
app = Flask(__name__)
users = {}
@app.route('/api/user/register', methods=['POST'])
def register_user():
    data = request.json
    email = data['email']
    if email in users:
        return jsonify({"error": "User with this email already exists."}), 400
    
    # ... Code to register user and generate token ...
    
    return jsonify({"userID": user_id, "name": data['name'], "email": email, "token": token}), 201
@app.route('/api/user/login', methods=['POST'])
def login_user():
    data = request.json
    email = data['email']
    if email not in users or users[email]['password'] != data['password']:
        return jsonify({"error": "Invalid credentials. Please try again."}), 401
    
    # ... Code to generate token ...
    
    return jsonify({"userID": users[email]['userID'], "name": users[email]['name'], "email": email, "token": token}), 200
if __name__ == '__main__':
    app.run(debug=True)

Timeline Service API:

from flask import Flask, request, jsonify
app = Flask(__name__)
timeline_data = {
    "user123": {
        "name": "John Doe",
        "timeline": [
            {
                "postID": "post1",
                "content": "Had a great day at the beach!",
                "postDate": "2023-07-20T12:30:00",
                "mediaType": "photo",
                "mediaURL": "https://example.com/image123.jpg"
            },
            {
                "postID": "post2",
                "content": "Excited about the new project.",
                "postDate": "2023-07-19T14:45:00",
                "mediaType": "text"
            }
        ]
    }
}
@app.route('/api/user/<string:user_id>/timeline', methods=['GET'])
def get_user_timeline(user_id):
    if user_id not in timeline_data:
        return jsonify({"error": "User not found."}), 404
    return jsonify(timeline_data[user_id]), 200
@app.route('/api/user/<string:user_id>/post', methods=['POST'])
def add_post_to_timeline(user_id):
    data = request.json
    # ... Code to validate and add the post to the timeline ...
    post = {
        "postID": "post3",
        "content": data['content'],
        "postDate": "2023-07-21T09:15:00",
        "mediaType": data['mediaType'],
        "mediaURL": data['mediaURL']
    }
    timeline_data[user_id]['timeline'].append(post)
    return jsonify(post), 201
@app.route('/api/user/<string:user_id>/post/<string:post_id>', methods=['PUT', 'DELETE'])
def edit_or_delete_post(user_id, post_id):
    # ... Code to edit or delete the post ...
    if request.method == 'PUT':
        # ... Code to update the post ...
        return jsonify(updated_post), 200
    elif request.method == 'DELETE':
        # ... Code to delete the post ...
        return jsonify({"message": f"Post with ID {post_id} has been deleted."}), 200
if __name__ == '__main__':
    app.run(debug=True)

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

from datetime import datetime

class FacebookTimeline:
    def __init__(self):
        self.posts = []

    def add_post(self, content, media_type=None, media_url=None):
        post = {
            "content": content,
            "media_type": media_type,
            "media_url": media_url,
            "timestamp": datetime.now()
        }
        self.posts.append(post)

    def get_timeline(self):
        return sorted(self.posts, key=lambda x: x["timestamp"], reverse=True)

    def add_life_event(self, event):
        self.posts.append({
            "content": f"Life Event: {event}",
            "timestamp": datetime.now()
        })

    def set_privacy(self, post_index, privacy):
        if 0 <= post_index < len(self.posts):
            self.posts[post_index]["privacy"] = privacy

    def view_activity_log(self):
        return self.posts

    def feature_post(self, post_index):
        if 0 <= post_index < len(self.posts):
            self.posts.insert(0, self.posts.pop(post_index))

# Example usage:
timeline = FacebookTimeline()

timeline.add_post("Had a great day at the beach!", "photo", "https://example.com/beach.jpg")
timeline.add_post("Excited about the new project.", "text")

timeline.add_life_event("Birthday")
timeline.add_life_event("Graduation")

timeline.set_privacy(0, "Friends")
timeline.set_privacy(1, "Public")

print("Timeline:")
print(timeline.get_timeline())

print("\nActivity Log:")
print(timeline.view_activity_log())

timeline.feature_post(2)

print("\nFeatured Timeline:")
print(timeline.get_timeline())

System Design — Online Poker Game

We will be discussing in depth -

Pic credits : Pinterest

What is Online Poker Game

Online Poker Game is a popular virtual version of the classic card game, Poker, that allows players from around the world to enjoy the excitement and thrill of poker online. The game enables multiple players to participate in real-time, providing an engaging and interactive platform for poker enthusiasts to showcase their skills and compete with others.

Important Features

  1. User Authentication and Registration: A secure user authentication system with options for registration and login is essential to ensure that players can create accounts and access the platform securely.
  2. Lobby and Game Selection: A user-friendly lobby interface is crucial for players to view available poker tables, choose stakes, game types, and find opponents to play against.
  3. Real-Time Gameplay: Online Poker Game should facilitate real-time gameplay with minimal latency to ensure an immersive and seamless gaming experience.
  4. Gameplay Options: The game should offer various poker variations like Texas Hold’em, Omaha, Seven-card stud, etc., to cater to a wide range of players’ preferences.
  5. In-Game Chat: Including an in-game chat feature allows players to interact, enhancing the social aspect of the game.
  6. Game History and Statistics: Keeping track of game history and providing player statistics helps in engaging users and improving their overall experience.
  7. Secure Transactions: Implementing a secure payment gateway for depositing and withdrawing money is crucial for real-money poker games.
  8. Anti-Cheating Measures: Integrating measures to detect and prevent cheating is essential to maintain a fair gaming environment.

Scaling Requirements — Capacity Estimation

For the sake of simplicity, let’s consider a small scale simulation for an Online Poker Game.

Assumptions:

  • Total number of users: 10,000
  • Daily active users (DAU): 2,000
  • Number of poker games played by user/day: 5
  • Total number of poker games played per day: 10,000 games/day
  • Read to write ratio: 100:1

Storage Estimation:

  • Let’s assume each poker game generates approximately 100 KB of data.
  • Total Storage per day: 10,000 games/day * 100 KB = 1 GB/day
  • For the next 3 years: 1 GB/day * 365 * 3 = 1.095 TB

Requests per Second:

  • Requests per second = 10,000 games/day / (24 hours * 3600 seconds) = ~0.12 requests/second
from flask import Flask, request, jsonify

app = Flask(__name__)

# Data structures to simulate game data
games = {}


@app.route('/create_game', methods=['POST'])
def create_game():
    data = request.get_json()
    game_id = data.get('game_id')
    # Check if the game_id already exists
    if game_id in games:
        return jsonify({'message': 'Game ID already exists'}), 400

    # Store the game data
    games[game_id] = data
    return jsonify({'message': 'Game created successfully'}), 201


@app.route('/get_game/<int:game_id>', methods=['GET'])
def get_game(game_id):
    # Check if the game_id exists
    if game_id not in games:
        return jsonify({'message': 'Game not found'}), 404

    # Return the game data
    return jsonify(games[game_id]), 200


@app.route('/play_game/<int:game_id>', methods=['POST'])
def play_game(game_id):
    # Check if the game_id exists
    if game_id not in games:
        return jsonify({'message': 'Game not found'}), 404

    # Simulate game play logic
    data = games[game_id]
    player_id = request.get_json().get('player_id')
    action = request.get_json().get('action')
    # Perform the player action on the game data (e.g., bet, fold, etc.)

    return jsonify({'message': f'Player {player_id} performed action: {action}'}), 200


if __name__ == '__main__':
    app.run()

Data Model — ER requirements

  1. User: Stores user information such as username, email, password, and account balance.
  2. Game: Represents individual poker games with attributes like game type, stakes, start time, and end time.
  3. Table: Each table hosts one game and has attributes like table ID, maximum number of players, and current players seated.
  4. Player: Represents a player’s association with a specific table, including attributes like player ID, seat number, and status (active, folded, etc.).
  5. Cards: Stores information about each card in the deck, including its value and suit.
  6. Chat: Manages in-game chat messages with attributes like message ID, sender, receiver, and timestamp.
+--------------------+             +--------------------+
|      Users         |             |       Games        |
+--------------------+             +--------------------+
| UserId (Primary Key)|----------<| GameId (Primary Key)|
| Username           |             | GameName           |
| Email              |             | GameType           |
| Password           |             | Stakes             |
+--------------------+             | CreatorUserId (FK) |
                                  +--------------------+
                                      |
                                      |
                                      |
                                      v
                             +-------------------+
                             |     UserGames     |
                             +-------------------+
                             | UserGameId (PK)   |
                             | UserId (FK)       |
                             | GameId (FK)       |
                             | JoinedAt         |
                             +-------------------+

High Level Design

  1. Traffic Handling: The system should be able to handle a large number of concurrent players, table creations, and game updates without significant performance degradation.
  2. Database Scalability: As the user base grows, the database should be able to handle the increasing load efficiently.
  3. Load Balancing: Implementing load balancing mechanisms is essential to distribute traffic evenly across multiple servers and prevent bottlenecks.
  4. Caching Strategy: Caching frequently accessed data can significantly reduce database load and improve response times.
  5. Frontend: Responsible for the user interface, game representation, and communication with backend services.
  6. Backend Application: Manages game logic, user authentication, and game state management.
  7. Game Engine: Implements the rules of poker and ensures fair gameplay.
  8. Database: Stores user data, game information, and chat messages.

Assumptions:

  • The system is read-heavy, with more users viewing ongoing games than creating new games.
  • The system needs to be highly available and reliable.
  • The system should be able to handle real-time updates and interactions during gameplay.
  • Players will have the option to follow and interact with each other during the game.

Main Components and Services for Online Poker Game:

  1. Mobile Client: Users will access the Online Poker Game through mobile applications or web browsers.
  2. Application Servers: These servers will handle the business logic, including game management, user authentication, and real-time interactions.
  3. Load Balancer: To distribute incoming requests to different application servers for load balancing.
  4. Cache (Memcache): Used to store frequently accessed data and improve response time.
  5. CDN: Content Delivery Network to optimize and deliver static assets like images and media.
  6. Database: NoSQL databases for storing user and game-related data.
  7. WebSocket Server: To enable real-time communication and game updates between players during gameplay.

Services:

  1. Authentication Service: Responsible for user registration, login, and token-based authentication.
  2. Game Management Service: Handles the creation, management, and deletion of poker games.
  3. User Interaction Service: Manages user interactions, such as following other players and sending/receiving game invites.
  4. Gameplay Service: Implements the rules and logic for different poker game variations.
  5. Real-Time Communication Service: Enables real-time communication between players during gameplay.
  6. Feed Generation Service: Generates and updates user-specific feeds based on the games they follow and their interactions.
  7. Payment Service: Integrates with a secure payment gateway to handle real-money transactions for players.
  8. Anti-Cheating Service: Implements algorithms and mechanisms to detect and prevent cheating during gameplay.
  9. Analytics Service: Collects and analyzes user activity data to gain insights into player behavior and game performance.
  10. Notification Service: Sends real-time notifications to players about game invites, updates, and other relevant events.
  11. Image/Video Processing Service: Handles image and video processing, including image resizing and thumbnail generation.
  12. Storage Service: Stores images, videos, and other media assets in a scalable and reliable storage system.

Authentication Service:

  • Functionality: User registration, login, and token-based authentication.
# authentication_service.py
from flask import Flask, request, jsonify
import bcrypt
import jwt
from datetime import datetime, timedelta
app = Flask(__name__)
# Dummy database for user storage
users = {}  # {username: {'password': hashed_password, 'user_id': user_id}}
# Secret key for JWT
SECRET_KEY = 'your_secret_key'
@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not username or not password:
        return jsonify({'message': 'Username and password are required'}), 400
    if username in users:
        return jsonify({'message': 'Username already exists'}), 400
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
    user_id = len(users) + 1
    users[username] = {'password': hashed_password, 'user_id': user_id}
    return jsonify({'message': 'Registration successful'}), 201
@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not username or not password or username not in users or not bcrypt.checkpw(password.encode('utf-8'), users[username]['password']):
        return jsonify({'message': 'Invalid credentials'}), 401
    # Generate and return JWT token upon successful login
    token = jwt.encode({'user_id': users[username]['user_id'], 'exp': datetime.utcnow() + timedelta(days=1)}, SECRET_KEY, algorithm='HS256')
    return jsonify({'message': 'Login successful', 'token': token}), 200
if __name__ == '__main__':
    app.run()

Game Management Service:

  • Functionality: Creation, management, and deletion of poker games.
# game_management_service.py
from flask import Flask, request, jsonify
import uuid
app = Flask(__name__)
# Dummy database for game storage
games = {}  # {game_id: {'game_name': name, 'game_type': type, 'stakes': stakes, 'creator_user_id': creator_user_id}}
@app.route('/create_game', methods=['POST'])
def create_game():
    data = request.get_json()
    game_name = data.get('game_name')
    game_type = data.get('game_type')
    stakes = data.get('stakes')
    creator_user_id = data.get('creator_user_id')
    game_id = str(uuid.uuid4())
    games[game_id] = {'game_name': game_name, 'game_type': game_type, 'stakes': stakes, 'creator_user_id': creator_user_id}
    return jsonify({'message': 'Game created successfully', 'game_id': game_id}), 201
@app.route('/get_game/<game_id>', methods=['GET'])
def get_game(game_id):
    if game_id not in games:
        return jsonify({'message': 'Game not found'}), 404
    return jsonify(games[game_id]), 200
@app.route('/delete_game/<game_id>', methods=['DELETE'])
def delete_game(game_id):
    if game_id not in games:
        return jsonify({'message': 'Game not found'}), 404
    del games[game_id]
    return jsonify({'message': 'Game deleted successfully'}), 200
if __name__ == '__main__':
    app.run()

Basic Low Level Design

from flask import Flask, request, jsonify

app = Flask(__name__)

users = {}  # Dictionary to store registered users
tables = {}  # Dictionary to store created poker tables
messages = []  # List to store chat messages


# User Authentication API
@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not username or not password:
        return jsonify({'message': 'Username and password are required'}), 400

    if username in users:
        return jsonify({'message': 'Username already exists'}), 400

    users[username] = {'password': password}
    return jsonify({'message': 'Registration successful'}), 201


@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not username or not password or username not in users or users[username]['password'] != password:
        return jsonify({'message': 'Invalid credentials'}), 401

    return jsonify({'message': 'Login successful', 'token': 'your_generated_token'}), 200


# Game Management API
@app.route('/create_table', methods=['POST'])
def create_table():
    data = request.get_json()
    # Extract table parameters like game type, stakes, etc.
    # Validate the data and create a new table entry in tables dictionary
    table_id = 'your_generated_table_id'
    tables[table_id] = {'params': data}
    return jsonify({'message': 'Table created', 'table_id': table_id}), 201


@app.route('/join_table', methods=['POST'])
def join_table():
    data = request.get_json()
    table_id = data.get('table_id')
    if table_id not in tables:
        return jsonify({'message': 'Table not found'}), 404

    # Handle player joining the table
    return jsonify({'message': 'Joined table successfully'}), 200


@app.route('/start_game', methods=['POST'])
def start_game():
    data = request.get_json()
    table_id = data.get('table_id')
    if table_id not in tables:
        return jsonify({'message': 'Table not found'}), 404

    # Check if the table has enough players and start the game
    return jsonify({'message': 'Game started'}), 200


@app.route('/end_game', methods=['POST'])
def end_game():
    data = request.get_json()
    table_id = data.get('table_id')
    if table_id not in tables:
        return jsonify({'message': 'Table not found'}), 404

    # End the game and calculate winners
    return jsonify({'message': 'Game ended'}), 200


# Gameplay API
@app.route('/bet', methods=['POST'])
def bet():
    data = request.get_json()
    # Validate data and handle betting logic
    return jsonify({'message': 'Bet placed'}), 200


@app.route('/fold', methods=['POST'])
def fold():
    data = request.get_json()
    # Validate data and handle folding logic
    return jsonify({'message': 'Folded'}), 200


@app.route('/show_cards', methods=['POST'])
def show_cards():
    data = request.get_json()
    # Validate data and handle showing cards logic
    return jsonify({'message': 'Cards shown'}), 200


# Chat API
@app.route('/send_message', methods=['POST'])
def send_message():
    data = request.get_json()
    sender = data.get('sender')
    receiver = data.get('receiver')
    message = data.get('message')
    if not sender or not receiver or not message:
        return jsonify({'message': 'Sender, receiver, and message are required'}), 400

    # Add the message to the messages list or save it in the database
    messages.append({'sender': sender, 'receiver': receiver, 'message': message})
    return jsonify({'message': 'Message sent'}), 200


if __name__ == '__main__':
    app.run()

API Design

  1. User Authentication API: Endpoints for user registration and login.
  2. Game Management API: Facilitates creating and joining tables, starting games, and ending games.
  3. Gameplay API: Allows players to perform actions like betting, folding, and showing cards during gameplay.
  4. Chat API: Handles in-game chat messages between players.
User Authentication API:
POST /register: Allows a user to register with the system.
POST /login: Allows a registered user to log in and receive an authentication token.

Game Management API:
POST /create_table: Creates a new poker table with specified parameters like game type and stakes.
POST /join_table: Allows a user to join an existing poker table with a given table ID.
POST /start_game: Starts the game on a table with sufficient players.
POST /end_game: Ends the game and calculates winners on a table.

Gameplay API:
POST /bet: Allows a player to place a bet during their turn.
POST /fold: Allows a player to fold their hand during their turn.
POST /show_cards: Allows a player to reveal their cards after the game is over.

Chat API:
POST /send_message: Allows a user to send a chat message during gameplay.

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

User Authentication and Registration:

from flask import Flask, request, jsonify
import bcrypt
app = Flask(__name__)
users = {}  # Dictionary to store registered users
@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not username or not password:
        return jsonify({'message': 'Username and password are required'}), 400
    if username in users:
        return jsonify({'message': 'Username already exists'}), 400
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
    users[username] = {'password': hashed_password}
    return jsonify({'message': 'Registration successful'}), 201
@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not username or not password or username not in users or not bcrypt.checkpw(password.encode('utf-8'), users[username]['password']):
        return jsonify({'message': 'Invalid credentials'}), 401
    return jsonify({'message': 'Login successful', 'token': 'your_generated_token'}), 200
if __name__ == '__main__':
    app.run()

Lobby and Game Selection:

from flask import Flask, jsonify
app = Flask(__name__)
# Placeholder data for available poker tables
poker_tables = [
    {'id': 1, 'game_type': 'Texas Hold\'em', 'stakes': 'Low', 'players': 3},
    {'id': 2, 'game_type': 'Omaha', 'stakes': 'High', 'players': 2},
    {'id': 3, 'game_type': 'Seven-card Stud', 'stakes': 'Medium', 'players': 4},
]
@app.route('/get_tables', methods=['GET'])
def get_tables():
    return jsonify(poker_tables), 200
@app.route('/join_table/<int:table_id>', methods=['POST'])
def join_table(table_id):
    table = next((t for t in poker_tables if t['id'] == table_id), None)
    if table is None:
        return jsonify({'message': 'Table not found'}), 404
    # Handle player joining the table
    return jsonify({'message': 'Joined table successfully'}), 200
if __name__ == '__main__':
    app.run()

Real-Time Gameplay and In-Game Chat:

For real-time gameplay and chat, you can extend the WebSocket implementation using Flask-SocketIO. The following example demonstrates the server-side code:

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
# Dictionary to store active game rooms
active_game_rooms = {}
@app.route('/')
def index():
    return render_template('index.html')
@socketio.on('connect')
def handle_connect():
    # Handle new player connection
    emit('message', {'data': 'Connected successfully'})
@socketio.on('disconnect')
def handle_disconnect():
    # Handle player disconnection
    pass
@socketio.on('join_game')
def handle_join_game(data):
    game_room_id = data.get('game_room_id')
    if game_room_id not in active_game_rooms:
        # Handle error if the game room does not exist
        pass
    # Handle player joining the game room
    join_room(game_room_id)
    emit('message', {'data': 'You joined the game'}, room=request.sid)
@socketio.on('chat_message')
def handle_chat_message(data):
    game_room_id = data.get('game_room_id')
    sender = data.get('sender')
    message = data.get('message')
    if game_room_id not in active_game_rooms:
        # Handle error if the game room does not exist
        pass
    # Handle the received chat message and broadcast it to all players in the same game
    emit('chat_message', {'sender': sender, 'message': message}, room=game_room_id)
if __name__ == '__main__':
    socketio.run(app)

System Design — Amazon Locker

We will be discussing in depth -

Pic credits : Pinterest

What is Amazon Locker

Amazon Locker is a convenient and secure self-service delivery and pick-up solution provided by Amazon. It aims to address the challenges of delivering packages to customers who may not have a fixed delivery address or prefer not to have packages delivered to their homes or workplaces.

Important Features

  1. Secure Storage: Amazon Lockers are equipped with robust security measures, including secure access codes and video surveillance, ensuring the safety of packages.
  2. Contactless Pickup and Drop-off: Users can easily pick up and drop off packages without any human interaction, making it a convenient and efficient solution.
  3. Multiple Locker Sizes: Lockers come in various sizes to accommodate packages of different dimensions, enhancing flexibility for customers and delivery personnel.
  4. 24/7 Accessibility: Amazon Lockers are accessible 24/7, allowing customers to pick up their packages at their convenience.

Scaling Requirements — Capacity Estimation

Smalll scale simulation of Amazon locker, let’s say —

Total number of users: 1.2 Billion

  • Daily active users (DAU): 300 Million
  • Number of packages picked up by user/day: 3
  • Total number of packages picked up per day: 900 Million packages/day
  • Read to write ratio: 100:1 (read-heavy system)
  • Total number of packages delivered/day = 1/100 * 900 Million = 9 Million/day

Storage Estimation:

  • Let’s assume, on average, each package’s size is 5 MB.
  • Total Storage per day: 9 Million * 5 MB = 45 TB/day
  • For the next 3 years, 45 TB * 5 * 365 = 82.125 PB (Petabytes)

Requests per Second:

  • Requests per second = 900 Million / (3600 seconds * 24 hours) ≈ 10,416 requests/second
class AmazonLocker:
    def __init__(self):
        self.locker_locations = {}  # Simulating locker locations
        self.packages = {}  # Simulating package data

    def add_locker_location(self, location_id, location_name, total_lockers):
        # Simulating adding a locker location with specified number of lockers
        self.locker_locations[location_id] = {'name': location_name, 'total_lockers': total_lockers}

    def add_package(self, package_id, package_size, locker_location):
        # Simulating adding a package to a locker location
        if locker_location not in self.locker_locations:
            return "Locker location not found."
        
        if package_id in self.packages:
            return "Package ID already exists."
        
        self.packages[package_id] = {'size': package_size, 'location': locker_location}
        self.locker_locations[locker_location]['total_lockers'] -= 1

    def pickup_package(self, package_id):
        # Simulating the process of picking up a package
        if package_id not in self.packages:
            return "Package not found."
        
        locker_location = self.packages[package_id]['location']
        self.locker_locations[locker_location]['total_lockers'] += 1
        del self.packages[package_id]
        return "Package picked up successfully."

# Creating an instance of AmazonLocker
amazon_locker = AmazonLocker()

# Adding a locker location with 1000 lockers
amazon_locker.add_locker_location(1, "Main Street Locker", 1000)

# Adding a package to the locker location with package_id and size 5 MB
amazon_locker.add_package("PKG123", 5, 1)

# Picking up the package with package_id "PKG123"
result = amazon_locker.pickup_package("PKG123")
print(result)  # Output: Package picked up successfully.

Data Model — ER requirements

  1. Locker: Represents an individual locker unit with a unique identifier and its current status (e.g., available, occupied).
  2. User: Stores user information, including unique user IDs, delivery preferences, and historical usage.
  3. Package: Represents a package with attributes such as size, delivery status, and recipient details.
  4. Location: Stores information about each locker location, including its address and available locker capacities.
User

user_id: int (Primary Key)
username: string
email: string
password: string

LockerLocation

location_id: int (Primary Key)
location_name: string
total_lockers: int

Locker

locker_id: int (Primary Key)
location_id: int (Foreign Key to LockerLocation)
occupied: bool

Package

package_id: int (Primary Key)
user_id: int (Foreign Key to User)
locker_id: int (Foreign Key to Locker)
photo_url: string
caption: string
post_timestamp: datetime
location: string

High Level Design

  1. User Interface: A user-friendly interface that allows customers to select an Amazon Locker location during checkout and receive their pickup codes.
  2. Locker Management Service: Responsible for tracking locker availability, assigning lockers to packages, and managing package pickup.
  3. Package Delivery Service: Handles the process of delivering packages from fulfillment centers to the selected Amazon Locker locations.
  4. Authentication and Security: Ensures secure access to lockers through unique pickup codes and authentication mechanisms.
  5. Location Expansion: The system should be easily scalable to add new locker locations in various geographic regions.
  6. Concurrent Users: The design must handle a large number of concurrent users accessing the lockers during peak times.
  7. Storage Capacity: The system should efficiently manage and allocate locker storage space for different package sizes.
  8. Redundancy and High Availability: To ensure continuous service, the system should be resilient with redundant components and high availability architecture.

Assumptions:

  • The system is read-heavy with more package pickups (reads) than package uploads (writes).
  • High reliability and availability are critical for package pickups and deliveries.

Main Components and Services:

  1. Mobile Client: Represents the users accessing the Amazon Locker platform through a mobile application.
  2. Application Servers: Handle read, write, and notification operations for the Amazon Locker platform.
  3. Load Balancer: Routes and directs requests from mobile clients to the appropriate application servers to balance the load.
  4. Cache (Memcache): Caches frequently accessed data to improve response times for read-heavy operations.
  5. CDN (Content Delivery Network): Improves the latency and throughput for delivering package-related data to users.
  6. Database (NoSQL): Stores data related to users, lockers, packages, follows, likes, and comments.
  7. Storage (HDFS or Amazon S3): Stores and manages the actual package photos and related metadata.

Main Services for Amazon Locker System:

  1. Package Service: Handles operations related to packages, such as uploading new packages, associating packages with lockers, and retrieving package information.
  2. User Service: Manages user-related operations, including user registration, authentication, and fetching user information.
  3. Locker Service: Manages the state of lockers, including marking them as occupied or available.

Basic Low Level Design

from flask import Flask, request, jsonify
import datetime

app = Flask(__name__)

# Sample data to be stored in the server
users = {}
locker_locations = {}
lockers = {}
packages = {}
follows = {}
likes = {}
comments = {}

# Endpoint for creating a new user
@app.route('/users', methods=['POST'])
def create_user():
    data = request.json
    user_id = len(users) + 1
    user = User(user_id, data['username'], data['email'], data['password'])
    users[user_id] = user
    return jsonify(user.__dict__), 201

# Endpoint for retrieving user information
@app.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
    user = users.get(user_id)
    if user:
        return jsonify(user.__dict__), 200
    else:
        return "User not found", 404

# Endpoint for adding a new locker location
@app.route('/locker_locations', methods=['POST'])
def add_locker_location():
    data = request.json
    location_id = len(locker_locations) + 1
    location = LockerLocation(location_id, data['location_name'], data['total_lockers'])
    locker_locations[location_id] = location
    return jsonify(location.__dict__), 201

# Endpoint for adding a new locker
@app.route('/lockers', methods=['POST'])
def add_locker():
    data = request.json
    locker_id = len(lockers) + 1
    locker = Locker(locker_id, data['location_id'])
    lockers[locker_id] = locker
    return jsonify(locker.__dict__), 201

# Endpoint for creating a new package
@app.route('/packages', methods=['POST'])
def create_package():
    data = request.json
    package_id = len(packages) + 1
    user_id = data['user_id']
    locker_id = data['locker_id']
    photo_url = data['photo_url']
    caption = data['caption']
    post_timestamp = datetime.datetime.now()
    location = data['location']
    package = Package(package_id, user_id, locker_id, photo_url, caption, post_timestamp, location)
    packages[package_id] = package
    return jsonify(package.__dict__), 201

# Endpoint for retrieving package information
@app.route('/packages/<int:package_id>', methods=['GET'])
def get_package(package_id):
    package = packages.get(package_id)
    if package:
        return jsonify(package.__dict__), 200
    else:
        return "Package not found", 404


if __name__ == '__main__':
    app.run()

API Design

User API

select_locker_location(user_id: str, location_id: str) -> str: Allows users to select an Amazon Locker location during checkout and returns a unique pickup code.
get_user_orders(user_id: str) -> List[Dict[str, Any]]: Retrieves a list of the user's past orders and their delivery status.

Locker API

get_available_lockers(location_id: str) -> List[str]: Returns a list of available locker IDs at a specific location.
assign_locker(package_id: str, locker_id: str) -> bool: Assigns a package to a specific locker.

Package API

create_package(package_details: Dict[str, Any]) -> str: Creates a new package with the provided details and returns the package ID.
get_package_details(package_id: str) -> Dict[str, Any]: Retrieves the details of a specific package.
update_package_status(package_id: str, status: str) -> bool: Updates the delivery status of a package.
# Data structures to simulate the database
users = {}
lockers = {}
packages = {}

# User API
def select_locker_location(user_id: str, location_id: str) -> str:
    # Check if the user exists in the database
    if user_id not in users:
        return "User not found."
    
    # Fetch available lockers at the specified location
    available_lockers = get_available_lockers(location_id)
    
    # Choose a locker randomly for simplicity (in a real system, a more sophisticated logic would be used)
    if not available_lockers:
        return "No lockers available at the selected location."
    
    selected_locker = available_lockers[0]
    
    # Assign the locker to the user's package
    assign_locker(user_id, selected_locker)
    
    return f"Your pickup code for Locker {selected_locker} is: {users[user_id]['pickup_code']}"

def get_user_orders(user_id: str) -> List[Dict[str, Any]]:
    # Check if the user exists in the database
    if user_id not in users:
        return []
    
    # In a real system, retrieve the user's orders and their delivery status from the database
    return users[user_id].get('orders', [])

# Locker API
def get_available_lockers(location_id: str) -> List[str]:
    # In a real system, fetch available lockers at the specified location from the database
    # For this example, we assume all lockers are available
    return [locker_id for locker_id, locker in lockers.items() if locker['location'] == location_id and not locker['occupied']]

def assign_locker(user_id: str, locker_id: str) -> bool:
    # Check if the locker exists in the database
    if locker_id not in lockers:
        return False
    
    # Check if the locker is available
    if lockers[locker_id]['occupied']:
        return False
    
    # Assign the locker to the user's package
    users[user_id]['assigned_locker'] = locker_id
    
    # Update the locker status to occupied
    lockers[locker_id]['occupied'] = True
    
    return True

# Package API
def create_package(package_details: Dict[str, Any]) -> str:
    # Generate a unique package ID (in a real system, this would be done differently)
    package_id = f"PKG-{len(packages) + 1}"
    
    # Add the package to the database
    packages[package_id] = package_details
    
    return package_id

def get_package_details(package_id: str) -> Dict[str, Any]:
    # Check if the package exists in the database
    if package_id not in packages:
        return {}
    
    return packages[package_id]

def update_package_status(package_id: str, status: str) -> bool:
    # Check if the package exists in the database
    if package_id not in packages:
        return False
    
    # Update the package status
    packages[package_id]['status'] = status
    return True

Complete Detailed Design

Coming soon! It will be covered on youtube channel.

Subscribe to youtube channel :

Complete Code implementation

Secure Storage:

# Function to simulate the secure storage feature
def secure_storage(package_id: str, access_code: str) -> bool:
    # Simulate the process of locking the locker and associating the access code with the package
    if package_id in packages and not packages[package_id]['locked']:
        packages[package_id]['access_code'] = access_code
        packages[package_id]['locked'] = True
        return True
    return False

Contactless Pickup and Drop-off:

# Function to simulate contactless pickup and drop-off
def contactless_pickup_dropoff(package_id: str) -> bool:
    # Simulate the process of unlocking the locker and removing the package
    if package_id in packages and packages[package_id]['locked']:
        packages[package_id]['locked'] = False
        return True
    return False

Multiple Locker Sizes:

# Function to add a new locker with a specified size
def add_locker(locker_id: str, size: str):
    lockers[locker_id] = {'size': size, 'occupied': False}

Mobile Integration:

# Function to generate a unique pickup code and associate it with a package
def generate_pickup_code(package_id: str) -> str:
    # Simulate the process of generating a unique pickup code for the package
    pickup_code = f"CODE-{package_id[-3:]}"
    packages[package_id]['pickup_code'] = pickup_code
    return pickup_code

Read next — how to Design the Dropbox.

Let me know if you have any questions in the comment section below. Subscribe/ Follow, Like/Clap and Stay Tuned!!

Day 1 : SQL Basics and Kick start of Advanced SQL Series

Day 2 : SQL Basics, Query Structure, Built In functions Conditions

Day 3 : Most Important Commands, Joins and Filters

Day 4 : Set Theory Operations, Stored Procedures and CASE statements in SQL

Day 5 : Wildcards, Aggregation and Sequences in SQL

Day 6 : Subqueries, Group by, order by and Having clauses in SQL and Analytical Functions

Day 7 : Window Functions, Grouping Sets and Constraints in SQL

Day 8 : BigQuery Basics, SELECT, FROM, WHERE and Date and Extract in BigQuery

Day 9 : Common Expression Table, UNNEST Clause, SQL vs NoSQL Databases

Day 10 : Triggers, Pivot and Cursors in SQL

Day 11 : Views, Indexes and Auto Increment in SQL

Day 12 : Query optimizations, Performance tuning in SQL

Day 13 : Introduction to MySQL, PostgreSQL and Mongo DB, Comparison between MySQL and PostgreSQL and Mongo DB, Introduction to SQL and NoSQL Databases

Day 14 : MySQL in Depth

Day 15 : PostgreSQL inDepth

Anyways, For Day 15 of 15 days of Advanced SQL, we will cover —

PostgreSQL inDepth

Github for Advanced SQL that you can follow —

All the projects, data structures, algorithms, system design, Data Science and ML, Data Engineering, MLOps and Deep Learning videos will be published on our youtube channel ( just launched).

Subscribe today!

System Design Case Studies — In Depth

Design Instagram

Design Messenger App

Design Twitter

Design URL Shortener

Design Dropbox

Design Youtube

Design API Rate Limiter

Design Web Crawler

Design Facebook’s Newsfeed

Design Yelp

Design Uber

Design Tinder

Design Tiktok

Design Whatsapp

Most Popular System Design Questions

Mega Compilation : Solved System Design Case studies

Complete Data Structures and Algorithm Series

Complexity Analysis

Backtracking

Sliding Window

Greedy Technique

Two pointer Technique

Arrays

Linked List

Strings

Stack

Queues

Hash Table/Hashing

Binary Search

1- D Dynamic Programming

Divide and Conquer Technique

Recursion

Github —

Some of the other best Series —

60 days of Data Science and ML Series with projects

30 Days of Natural Language Processing ( NLP) Series

30 days of Machine Learning Ops

30 days of Data Structures and Algorithms and System Design Simplified

60 Days of Deep Learning with Projects Series

30 days of Data Engineering with projects Series

Data Science and Machine Learning Research ( papers) Simplified **

100 days : Your Data Science and Machine Learning Degree Series with projects

23 Data Science Techniques You Should Know

Tech Interview Series — Curated List of coding questions

Complete System Design with most popular Questions Series

Complete Data Visualization and Pre-processing Series with projects

Complete Python Series with Projects

Complete Advanced Python Series with Projects

Kaggle Best Notebooks that will teach you the most

Complete Developers Guide to Git

Exceptional Github Repos — Part 1

Exceptional Github Repos — Part 2

All the Data Science and Machine Learning Resources

210 Machine Learning Projects

Tech Newsletter —

If you are interested, you can join my newsletter through which I send tech interview tips, techniques, patterns, hacks — Software Development, ML, Data Science, Startups and Technology projects to more than 30K readers. You can subscribe to Tech Brew :

For Python Projects —

For complete 60 days of Data Science and ML : Day 1 — Day 60 : Quick Recap of 60 days of Data Science and ML

Follow for more updates. Stay tuned and keep coding!

For other projects, tune to —

Build Machine Learning Pipelines( With Code)

Recurrent Neural Network with Keras

Clustering Geolocation Data in Python using DBSCAN and K-Means

Facial Expression Recognition using Keras

Hyperparameter Tuning with Keras Tuner

Custom Layers in Keras

Tech
Software Development
Data Science
Machine Learning
Programming
Recommended from ReadMedium