Design Social Media app like TikTok:
The app should have below functionality:
- Feed
- Infinite-scrolling
- Pagination
- Media(video)
- Friends network
- Follow/unfollow
- Offline support
Always start with the clarification questions and clear the requirements.
1. Clarify requirements and assumptions:
Clarification Questions:
- What platforms (iOS, Android, web) should the app support?
- What is the target audience for the app, and what are their demographics?
- What is the expected scale of the app in terms of the number of users and the volume of video content?
- What are the requirements for offline support and data synchronization?
- What are the expectations for user engagement features, such as likes, comments, and sharing?
- Any file size check or limitations
- Content filtering option support
Functional requirements:
- Infinite-scrolling feed of user-generated videos
- Pagination for efficient loading of videos
- Support for uploading and playing media (images/videos)
- Friends network with follow/unfollow functionality
- Offline support for viewing previously loaded content
Non-functional requirements:
- High performance and low latency for smooth video playback
- Scalability to handle a growing user base and increasing content
- Efficient network usage to minimize data consumption
- Reliable offline experience with proper data synchronization
Assumptions:
- The app will be developed natively for Android using Kotlin
- The backend infrastructure will be provided and accessible via APIs
- User authentication and profile management will be handled separately
2. Define the client-server communication:
API design:
- RESTful APIs for video retrieval, user actions, and data synchronization
- Pagination API to load videos in chunks (e.g., /api/videos?page=1&limit=20)
- WebSocket or long-polling for real-time updates (e.g., new video notifications)
Data synchronization:
- Incremental synchronization to fetch only new or updated videos
- Background synchronization to keep the feed up to date when offline
- Conflict resolution mechanism to handle simultaneous updates
3. Choose the appropriate storage mechanism:
Local storage:
- SQLite database for structured data (e.g., video metadata, user profiles)
- SharedPreferences for simple key-value pairs (e.g., user preferences, settings)
- File system for storing cached videos and images
Cloud storage:
- Scalable object storage (e.g., Amazon S3, Google Cloud Storage) for video files
- Content Delivery Network (CDN) for efficient video delivery and reduced latency
4. Develop a caching strategy:
Video caching:
- Implement a two-level caching mechanism: memory cache and disk cache
- Memory cache (e.g., LruCache) for fast access to recently viewed videos
- Disk cache for persistent storage of downloaded videos
- Prefetch and cache videos ahead of time for smoother playback
Cache invalidation at client:
- In-Memory Cache (e.g., LruCache) Invalidation:
- When a video is downloaded from the server, the app stores it in the in-memory cache for fast access.
- Each cached video entry in the in-memory cache is associated with a unique key (e.g., video ID) and a timestamp indicating when it was cached.
- The app sets a TTL (Time-To-Live) value for each cached video based on factors like video popularity or update frequency.
- When the app needs to access a video, it first checks the in-memory cache using the video’s unique key.
- If the video is found in the cache, the app checks if the current timestamp exceeds the sum of the cached timestamp and the TTL.
- If the TTL has expired, the app invalidates the cached video entry and removes it from the in-memory cache.
- If the TTL is still valid, the app retrieves the video from the in-memory cache and serves it to the user.
- The app can also implement a background process that periodically scans the in-memory cache and removes expired entries based on their TTL.
2. Disk Cache Invalidation:
- Videos that are downloaded from the server are also stored in the disk cache for persistent storage and offline access.
- Each cached video file on the disk is associated with a unique filename (e.g., based on the video ID) and a metadata file containing additional information like the timestamp and TTL.
- When the app needs to access a video, it first checks the disk cache using the video’s unique filename.
- If the video file is found on the disk, the app reads the associated metadata file to retrieve the cached timestamp and TTL.
- The app compares the current timestamp with the sum of the cached timestamp and the TTL.
- If the TTL has expired, the app invalidates the cached video file and removes it from the disk cache.
- If the TTL is still valid, the app retrieves the video file from the disk cache and serves it to the user.
- The app can also implement a background process that periodically scans the disk cache and removes expired video files based on their TTL.
3. Cache Invalidation Based on Server Notifications:
- In addition to the TTL-based invalidation, the app can also invalidate cached videos based on notifications from the server.
- When a video is updated on the server (e.g., new content, edited metadata), the server can send a push notification or a specific invalidation signal to the app.
- The notification or signal includes the unique identifier (e.g., video ID) of the updated video.
- Upon receiving the notification, the app checks its in-memory and disk cache for the specified video.
- If the video is found in either cache, the app invalidates the cached entry and removes it from the respective cache.
- The app can then request the updated video from the server and cache it again with a new timestamp and TTL.
4. Cache Invalidation During App Updates:
- When a new version of the app is released, there might be changes in the video format, encoding, or caching mechanisms.
- During the app update process, the app can invalidate and clear the entire in-memory and disk cache.
- This ensures that any outdated or incompatible cached videos are removed, and the app starts fresh with the latest caching implementation.
By implementing these client-side cache invalidation mechanisms, the TikTok-like app can effectively manage the in-memory and disk cache, ensuring that users have access to the most up-to-date video content.
The combination of TTL-based invalidation, server notifications, and cache clearing during app updates helps maintain data freshness and optimal app performance.
5. Optimize data loading and transfer:
Pagination:
- Implement infinite-scrolling using the pagination API
- Load videos in smaller chunks to reduce initial load time
- Prefetch the next set of videos as the user approaches the end of the current list
Efficient media loading:
- Lazy-load video thumbnails and metadata to minimize data usage
- Prioritize loading of visible videos and defer loading of off-screen videos
- Implement video compression and adaptive bitrate streaming for optimal playback
6. Ensure scalability and performance:
Scalability:
- Design the backend infrastructure to handle increasing users and video uploads
- Leverage containerization and auto-scaling to dynamically adjust server capacity
- Use a distributed storage system for handling a large volume of video data
Performance optimization:
- Minimize API response times through caching and efficient database queries
- Compress video files to reduce storage and bandwidth requirements
- Optimize video encoding and streaming protocols for faster playback
7. Prioritize security and privacy:
Authentication and authorization:
- Implement secure user authentication using OAuth or JWT tokens
- Enforce proper access controls for user-specific actions (e.g., follow/unfollow)
Secure data transmission:
- Use HTTPS for all API communications to encrypt data in transit
- Implement SSL/TLS for secure video streaming
- Utilize encryption algorithms (e.g., AES) for sensitive data storage
8. Plan for internationalization and localization:
Language support:
- Design the app to support multiple languages and locales
- Use string resources for easy translation and localization
- Handle right-to-left (RTL) layouts for languages like Arabic and Hebrew
Date/time and formatting:
- Display dates and times according to the user’s locale
- Format numbers, currencies, and other locale-specific data appropriately
9. Incorporate error handling and resilience:
Network error handling:
- Implement proper error handling for network failures and API errors
- Display user-friendly error messages and provide retry options
- Utilize exponential backoff for retrying failed network requests
Offline resilience:
- Implement offline support by caching videos and metadata locally
- Allow users to view previously loaded content when offline
- Synchronize data seamlessly when the network connection is restored
10. Consider Android-specific optimizations:
Battery and resource optimization:
- Optimize battery consumption by reducing background processing
- Utilize Android’s power-saving features (e.g., Doze mode, App Standby)
- Minimize CPU and memory usage through efficient algorithms and data structures
Push notifications:
- Implement Firebase Cloud Messaging (FCM) for push notifications
- Notify users about new videos, comments, and other relevant updates
- Allow users to customize notification preferences
Trade-offs and Chosen Approaches:
- Offline Support vs. Data Freshness:
- Approach: Implement a hybrid approach with local caching for offline support and efficient synchronization mechanisms to update data when online. Clearly communicate data freshness to users.
- Rationale: Providing offline access to previously loaded content enhances the user experience and allows users to engage with the app even in low-connectivity scenarios. By transparently communicating data freshness, we set the right expectations for users.
- Pagination vs. Infinite Scrolling:
- Approach: Implement infinite scrolling with pagination for efficient data loading and improved user experience.
- Rationale: Infinite scrolling provides a seamless and immersive browsing experience for users, eliminating the need for manual pagination. By loading data in smaller chunks using pagination APIs, we can optimize network usage and reduce initial load time.
Client-Side Components and Interaction:
- Main Screen: The central hub that provides access to different features.
- Video Feed: Displays the infinite-scrolling list of user-generated videos.
- Video Playback: Handles video playback, pause, seek, mute/unmute, and fullscreen.
- Like/Comment: Allows users to like and comment on videos.
- Share: Enables users to share videos on other platforms.
- Report: Allows users to report inappropriate content.
- Pagination: Loads the next page of videos and prefetches them for smooth scrolling.
3. User Profile: Shows user details, user-specific videos, and allows profile editing.
4. Friends Network:
- The client retrieves the user’s friends list from the server.
- The server responds with the list of friends and their profiles.
- The client caches the friends list locally for offline access.
- When the user follows/unfollows someone, the client sends a request to the server to update the relationship.
5. Video Upload: Enables users to capture or select videos, trim, add filters, add descriptions, and upload videos to the server.
6. Settings: Provides access to notification settings, privacy settings, and logout functionality.
The Offline Manager component handles local caching of videos and metadata, data synchronization with the server, and conflict resolution when the app is online.
System Architecture and Components:
When designing the TikTok-like app, I recommend using the MVVM (Model-View-ViewModel) architectural pattern. MVVM promotes a clear separation of concerns, enhances testability, and aligns well with the modern development practices in Android.
Now, let’s see how the components of the TikTok-like app fit into the MVVM architecture:
Model:
Video
: Represents the data structure for a video, including its metadata (title, description, user, likes, comments).User
: Represents the data structure for a user, including their profile information and social connections.Comment
: Represents the data structure for a comment on a video.VideoRepository
: Acts as a mediator between the ViewModel and the data sources (local database and remote server). It handles the retrieval and storage of videos and related data.
View:
VideoFeedActivity/Fragment
: Displays the main screen of the app, showing the infinite-scrolling list of videos.VideoPlayerActivity/Fragment
: Handles the playback of a selected video, including controls for like, comment, and share.UserProfileActivity/Fragment
: Displays the user's profile information and their uploaded videos.VideoUploadActivity/Fragment
: Allows users to upload new videos, add captions, and apply filters.
ViewModel:
VideoFeedViewModel
: Contains the business logic for the video feed, such as loading videos, handling pagination, and managing user interactions (like, comment, share).VideoPlayerViewModel
: Handles the logic for playing a specific video, retrieving comments, and updating video metadata based on user actions.UserProfileViewModel
: Manages the user's profile data, including their uploaded videos and social connections.VideoUploadViewModel
: Handles the video upload process, including video compression, metadata input, and communication with the server.
Additional Components:
VideoService
: Communicates with the server API to fetch and upload videos, handle user actions, and sync data.OfflineManager
: Manages the local caching of videos and metadata, handles offline access, and synchronizes data with the server.NotificationManager
: Handles the display of push notifications and manages the notification channels and settings.AnalyticsManager
: Tracks user interactions and app usage metrics, and sends the data to an analytics service for insights and reporting.
By organizing the components into the MVVM architecture, we achieve a modular and maintainable structure for the TikTok-like app. The ViewModel encapsulates the business logic and exposes the necessary data and actions to the View. The Model represents the data and the repositories for accessing and persisting the data. The View is responsible for rendering the UI and capturing user interactions.
Storage and API at Server side:
- Videos are stored in a scalable object storage (e.g., Amazon S3) for efficient retrieval and delivery.
- Video metadata, user profiles, and social graph data are stored in a NoSQL database (e.g., MongoDB) for flexibility and scalability.
- RESTful APIs are used for video retrieval, user actions, and data synchronization.
- WebSocket is used for real-time updates and notifications.
Additional Considerations:
- Implement a content moderation system to detect and filter out inappropriate or offensive videos.
- Provide features for user engagement, such as liking, commenting, and sharing videos.
- Optimize the app for different network conditions and device capabilities.
- Implement analytics and tracking to gain insights into user behavior and app performance.
- Continuously monitor and improve the app based on user feedback and metrics.
API Design:
- RESTful APIs:
- RESTful APIs will be used for video retrieval, user actions, and data synchronization.
- The client will send HTTP requests (GET, POST, PUT, DELETE) to specific endpoints to perform actions like retrieving videos, liking/commenting on videos, following/unfollowing users, etc.
- The server will respond with JSON or XML data containing the requested information or the status of the performed action.
- Example endpoints:
- GET /api/videos: Retrieve a list of videos
- POST /api/videos: Upload a new video
- PUT /api/videos/{id}: Update video metadata
- DELETE /api/videos/{id}: Delete a video
- POST /api/likes: Like a video
- POST /api/comments: Add a comment to a video
- POST /api/follow: Follow a user
2. Pagination API:
- The pagination API will be used to load videos in chunks, reducing the amount of data transferred in a single request.
- The client will send a GET request to the
/api/videos
endpoint with pagination parameters (e.g.,page
andlimit
). - Example:
/api/videos?page=1&limit=20
will retrieve the first 20 videos. - The server will respond with the requested chunk of videos along with metadata like the total count of videos and the next page URL.
- The client can then load the next chunk of videos by making a request to the provided next page URL.
3. Real-time Updates:
- For real-time updates, such as new video notifications, I would choose WebSocket over long-polling.
Rationale:
- WebSocket provides a full-duplex, persistent connection between the client and the server, allowing real-time bi-directional communication.
- It eliminates the need for the client to repeatedly poll the server for updates, reducing latency and improving efficiency.
- WebSocket is well-suited for scenarios that require instant updates and high interactivity, like real-time notifications.
- The client will establish a WebSocket connection with the server and subscribe to relevant channels (e.g., new video notifications for followed users).
- When a new video is uploaded, the server will push a notification to the subscribed clients through the WebSocket connection.
- The client can then update the UI in real-time, showing the new video in the user’s feed.
4. Data Synchronization:
4.1 Incremental Synchronization:
- Incremental synchronization will be used to fetch only new or updated videos since the last synchronization.
- The client will keep track of the timestamp or version of the last synchronized video.
- When requesting updates, the client will send the last synchronized timestamp/version to the server.
- The server will respond with only the videos that have been added or updated since that timestamp/version.
- This approach minimizes the amount of data transferred and speeds up the synchronization process.
4.2 Background Synchronization:
- WorkManager: Android’s WorkManager API allows scheduling background tasks that are executed based on certain conditions, such as network availability or device charging state.
- We can use WorkManager to schedule periodic background synchronization tasks that fetch new videos from the server and update the local cache. However, the frequency of these tasks is subject to the system’s optimization policies.
- Firebase Cloud Messaging (FCM): Instead of relying on periodic background synchronization, we can leverage FCM to send notifications to the app when new videos are available. When the user interacts with the notification or opens the app, we can trigger the synchronization process to fetch the new videos. This approach ensures that the app receives updates without the need for continuous background processing.
- Foreground Service: In cases where real-time updates and continuous background synchronization are critical, we can consider using a foreground service. A foreground service runs in the background but displays a persistent notification to the user, indicating that the app is performing some ongoing work. However, this approach should be used sparingly and only when absolutely necessary, as it can impact the user experience and battery life.
4.3 Conflict Resolution:
- Conflict resolution will be used to handle simultaneous updates made by multiple clients.
- Each video will have a version number that increments with every update.
- When a client updates a video (e.g., likes/comments), it will send the video’s current version number along with the update request.
- The server will compare the received version number with the version number stored in the database.
- If the versions match, the server will apply the update and increment the version number.
- If the versions don’t match, indicating a conflict, the server will reject the update and return an error response to the client.
- The client can then fetch the latest version of the video from the server, merge the changes (if applicable), and retry the update with the updated version number.
- This optimistic concurrency control approach ensures data consistency and prevents conflicting updates from overwriting each other.
1. Here a good question can arise why we are not using PushNotification for real time update?
WebSocket vs. Push Notifications for Real-time Updates: Push notifications are indeed a suitable approach for delivering updates to users when the app is not actively running.
Here are some advantages and disadvantages of using WebSocket and push notifications:
WebSocket Advantages:
- Enables real-time, bi-directional communication between the client and the server.
- Provides low-latency updates and allows for instant data synchronization.
- Suitable for scenarios that require continuous data exchange and high interactivity.
WebSocket Disadvantages:
- Requires the app to be running and connected to the server to receive updates.
- May consume more battery and resources compared to push notifications.
Push Notification Advantages:
- Allows sending updates to users even when the app is not actively running.
- Conserves battery and resources by not requiring a persistent connection.
- Suitable for delivering important updates and engaging users.
Push Notification Disadvantages:
- Relies on the device’s push notification service (FCM for Android) and may have some delivery delays.
- Limited payload size compared to WebSocket.
Considering your perspective, using push notifications for sending new video notifications makes sense. It allows users to receive updates even when the app is not running and conserves system resources.
WebSocket can still be used for real-time interactions within the app, such as live comments or user presence indicators. The choice between WebSocket and push notifications depends on the specific requirements and the desired user experience.
2. Which approach you will choose for background Synchnization?
By combining FCM and WorkManager, we can achieve a balanced approach to background synchronization in the TikTok-like app:
- When a new video is uploaded, the server sends a notification through FCM to the relevant users’ devices.
- Upon receiving the notification, the app can schedule a background synchronization task using WorkManager to fetch the new videos.
- WorkManager takes care of executing the synchronization task based on system conditions and ensures that it runs efficiently.
- If the device is offline or the synchronization fails, WorkManager can automatically retry the task based on the defined retry policy.
- The app can also schedule periodic background synchronization tasks using WorkManager to keep the video feed up to date, even if no new video notifications are received.
This combination of FCM and WorkManager provides a reliable and efficient solution for handling background synchronization in the TikTok-like app
3. How this works? Upon receiving the notification, the app can schedule a background synchronization task using WorkManager to fetch the new videos.
When the app receives a notification through Firebase Cloud Messaging (FCM), it can trigger a background synchronization task using WorkManager. Here’s how it works internally in Android:
- FCM Notification Received:
- When a new video is uploaded, the server sends a notification through FCM to the relevant users’ devices.
- The FCM SDK in the app receives the notification and invokes the
onMessageReceived
method in theFirebaseMessagingService
class. - Inside the
onMessageReceived
method, the app can extract the necessary information from the notification payload, such as the video ID or timestamp.
2. Scheduling WorkManager Task:
- After receiving the notification, the app can schedule a background synchronization task using WorkManager.
- To do this, the app creates a new instance of the
OneTimeWorkRequest
orPeriodicWorkRequest
class, depending on whether it's a one-time task or a recurring task. - The app specifies the
Worker
class that defines the actual synchronization logic and any additional configuration, such as constraints or retry policy. - The app then enqueues the work request using the
WorkManager.enqueueUniqueWork()
method, providing a unique name for the work and theExistingWorkPolicy
to handle conflicts if the same work is already enqueued.
3. Executing the Synchronization Task:
- When the system conditions are met (e.g., network availability, device charging), WorkManager automatically executes the enqueued synchronization task.
- The
doWork()
method of the specifiedWorker
class is invoked, and this is where the actual synchronization logic is implemented. - Inside the
doWork()
method, the app can perform the necessary network requests to fetch the new videos from the server. - The app can use libraries like Retrofit or Volley to make HTTP requests to the server’s API endpoints and retrieve the video data.
- The fetched video data can be parsed and stored in the local database or cache for offline access.
4. Handling Failures and Retries:
- If the synchronization task fails due to network issues or other errors, WorkManager automatically handles the retry process based on the specified retry policy.
- The retry policy can be configured using the
setBackoffCriteria()
method of the work request, specifying the initial delay, backoff policy (linear or exponential), and the maximum number of retries. - WorkManager takes care of scheduling the retries and ensures that the synchronization task is executed when the system conditions are favorable.
Practical Example:
Let’s consider a practical example of how the app would handle a specific user scenario:
User Scenario: Uploading and Viewing a New Video
- User A opens the app and decides to upload a new video.
- User A records a 30-second video using the app’s built-in camera functionality.
- After recording, User A adds a caption, selects relevant hashtags, and applies a filter to the video.
- User A taps the “Post” button to upload the video.
- The app compresses the video and sends it to the server via a RESTful API endpoint (
POST /api/videos
). - The server processes the video, generates thumbnails, and stores the video file in a scalable object storage (e.g., Amazon S3).
- The server saves the video metadata (e.g., caption, hashtags, user details) in a NoSQL database (e.g., MongoDB).
- The server sends a success response back to the app, including the video’s unique identifier.
- The app displays a confirmation message to User A, indicating that the video has been successfully uploaded.
- Meanwhile, the server sends push notifications (via Firebase Cloud Messaging) to User A’s followers, informing them about the new video.
- User B, who is a follower of User A, receives the push notification about the new video.
- User B opens the app and navigates to the video feed.
- The app sends a request to the server’s RESTful API endpoint (
GET /api/videos
) to retrieve the latest videos, including User A's new video. - The server queries the database and returns a paginated list of videos, along with their metadata and thumbnails.
- The app displays the video feed to User B, showing User A’s new video along with other recent videos.
- User B scrolls through the feed and comes across User A’s video.
- User B taps on User A’s video to view it in full screen.
- The app sends a request to the server to retrieve the video file from the object storage.
- The server fetches the video file from the object storage and starts streaming it to the app.
- The app buffers the video and starts playing it for User B.
- User B can interact with the video by liking, commenting, or sharing it with others.
- The app sends requests to the server’s API endpoints (
POST /api/likes
,POST /api/comments
,POST /api/share
) to record User B's interactions. - The server updates the video’s metadata in the database to reflect the new likes, comments, and shares.
- If User B is offline and has previously loaded videos, the app retrieves the cached videos from the local storage for offline viewing.
Practical Example using MVVM:
Let’s consider a practical example of how the MVVM architecture would be applied in the TikTok-like app:
- User opens the app and lands on the video feed screen (VideoFeedActivity/Fragment).
- The VideoFeedActivity/Fragment binds to the VideoFeedViewModel and observes the list of videos exposed by the ViewModel.
- The VideoFeedViewModel communicates with the VideoRepository to fetch the latest videos from the server or the local cache.
- The VideoRepository uses the VideoService to make API requests to the server and retrieves the video data.
- The VideoRepository also interacts with the OfflineManager to cache the fetched videos locally for offline access.
- The VideoFeedViewModel processes the retrieved video data, applies any necessary transformations, and exposes it to the VideoFeedActivity/Fragment.
- The VideoFeedActivity/Fragment renders the list of videos using RecyclerView and displays them to the user.
- When the user scrolls through the feed, the VideoFeedViewModel handles the pagination logic, loading the next set of videos as needed.
- If the user taps on a video, the VideoPlayerActivity/Fragment is launched to play the selected video.
- The VideoPlayerActivity/Fragment binds to the VideoPlayerViewModel and observes the video data and related information (likes, comments).
- The VideoPlayerViewModel communicates with the VideoRepository to fetch the video details and comments.
- The VideoPlayerActivity/Fragment renders the video player, displays the video metadata, and allows the user to interact with the video (like, comment, share).
- When the user performs an action (e.g., likes a video), the VideoPlayerViewModel handles the logic and communicates with the VideoRepository to update the video metadata on the server.
- The AnalyticsManager tracks the user’s interactions and sends the data to an analytics service for further analysis.
This example demonstrates how the MVVM architecture enables a clear separation of responsibilities and promotes a reactive and testable approach to building the TikTok-like app. The ViewModel encapsulates the business logic, the Model represents the data, and the View focuses on rendering the UI and capturing user interactions.
Thanks for reading:
👏 Please clap for the story and follow me 👉
For detailed Mobile System Design Interview Preparation, you can checkout the design template, trade-offs, which should be the preferred way, how to make decisions and mold the design interview with covering more breadth and depth you can check out this detailed course Link or you can connect me on topmate.io.