Deeply Nested Comments Architecture

Ijlal AhmadIjlal Ahmad
8 min read

Overview

Ever wondered how nested comments are implemented? Some sites like YouTube or Instagram limit the level of nested comments to only one level. However, platforms like Reddit or Facebook took nested comments to a whole new level, allowing users to reply deeply nested comments, providing a clear and precise context.

While platforms like YouTube or Instagram limit nested behavior to only one level, where replies to nested comments are simply appended by the username of the parent comment, deeply nested comments offer a more satisfying experience. Deeply nested comments ensure absolute context, allowing users to navigate through discussions with precision.

Despite the widespread interest in deeply nested comments, comprehensive tutorials covering frontend, backend, and database models are scarce. In this article, I aim to provide an overview of deeply nested comments architecture, covering the frontend, backend, and database implementation practices involved in this module.

In this article, we'll focus solely on the theoretical aspects, omitting complex system design patterns like lazy loading, caching, and pagination for large comment threads. While these advanced concepts significantly enhance efficiency and performance, they require a solid understanding of backend foundations. Therefore, we'll reserve them for future articles. For now, let's delve into the fundamentals of implementing nested comments.

Database Design

In system design, the database design is the crucial starting point. When considering the implementation of nested behavior, the choice of database type becomes pivotal. While non-relational databases offer flexibility in schema and storage, relational databases outshine in both schema management and performance.

Relational vs. Non-Relational Databases

Relational vs. non-relational databases: Understanding the difference

Non-Relational Databases

Non-relational databases, with their document and collection structure, seem like a natural fit for nested comments. However, limitations arise due to document size restrictions. Even though comments can be nested within a single document, scalability becomes an issue. Dividing comments across multiple documents or collections leads to performance degradation, especially when querying nested data.

Relational Databases

Contrary to initial assumptions, relational databases excel in handling nested comments. Leveraging the concept of circular or self-referential models, a single model can accommodate both base and nested comments. This approach simplifies schema design and ensures optimal performance.

Ok, Enough talk show me the Approaches

Top Down Vs Bottom Up Approaches

Approach 1 (Top Down, Theoretical)

CommentModel {
    id: number,
    postId: number    // foreign key to posts table
    comment: string,
    commentorId: number,
    createdAt: Date,
    replies: CommentModel[]
}

In this approach, each comment contains an array (replies) of nested comments of the same type. This design theoretically allows for infinite nesting, providing a clear hierarchy of comments within comments. However, while conceptually elegant, this approach faces practical limitations, especially when implemented in relational databases.

The primary drawback is that relational databases adhere to a flat schema structure, where each row represents a single entity or record. Storing arrays violates this principle and can lead to inefficiencies in querying and data retrieval. Additionally, relational databases are optimized for efficient JOIN operations, which are essential for querying nested data structures. Storing nested comments as arrays complicates JOIN operations and can significantly impact performance.

Approach 2 (Bottom Up, Practical)

CommentModel {
    id: number,
    postId: number    // foreign key to posts table
    comment: string,
    commentorId: number,
    createdAt: Date,
    parentId: number | null // null for top level comments
}

In this approach, each comment contains a reference (parentId) to its parent comment. The parentId establishes a hierarchical relationship between comments, enabling straightforward querying and navigation through nested comment threads. This approach aligns well with relational database principles and facilitates efficient data retrieval and storage.

By utilizing a self-referential model, the relational database can easily represent nested comments without violating the flat schema structure. Each comment exists as an independent entity, with its parentId linking it to its parent comment. This design simplifies querying, as we can fetch all the comments of a single level if we know the parentId without touching other comments. This facilitates batch processing on the network side allowing us to integrate pagination on the go.

Implementation Benefits

  • Optimized Querying: Retrieving top-level comments and their replies is streamlined, enhancing database query efficiency.

  • Scalability: Pagination can be seamlessly integrated, ensuring smooth navigation through large comment threads.

  • Network Efficiency: Network traffic is minimized as only necessary comments are fetched, reducing load times for users.

While the theoretical elegance of Approach 1 may seem appealing, the practical limitations it poses make it unsuitable for implementation in relational databases. Approach 2, with its bottom-up design and self-referential model, proves to be the pragmatic choice for efficiently implementing nested comments. Its alignment with relational database principles, along with its simplicity and scalability, makes it the ideal solution for managing nested comment threads.

Backend

Backend Development : Understanding the basics - PloPdo

When designing the backend APIs for nested comments, the design pattern remains consistent regardless of the backend framework chosen, whether

it's Node.js, Django, Spring, or Golang. The key focus lies in optimizing the querying of the database to fetch comments efficiently, ensuring both performance and network optimization. As discussed earlier, the database design is already established, eliminating the need for additional consideration.

Fetching of Comments

Manual Way

  • Fetching Top-level Comments

    To retrieve the top-level comments of a post, a simple query is executed to fetch all comments associated with the desired postId and where the parentId is null. Since top-level comments have no parent, this query efficiently retrieves all relevant comments for the post.

  • Fetching 1st-level Nested Comments

    These are typically the replies to top-level comments. To fetch 1st-level nested comments for a specific comment, a query retrieves all comments related to the post and with a parentId corresponding to the desired comment. While it may seem inefficient to query for each comment's replies individually, this on-demand fetching optimizes network usage.

  • Fetching nth-level Nested Comments

    Similar to fetching 1st-level nested comments, the process involves querying comments based on the postId and parentId of the desired comment. However, to optimize network usage, platforms like Facebook or Reddit typically limit the initial fetch to 1 or 2 levels of comments. Further levels or comments are fetched on demand, ensuring efficient network utilization.

MPTT Algorithm for Nested Comments

An alternative approach to managing nested comments is the Modified Preorder Tree Traversal (MPTT) algorithm. This algorithm assigns each comment a left and right value, allowing for efficient querying of hierarchical data. While beyond the scope of this article, the MPTT algorithm provides another method for handling nested comments, offering advantages in certain scenarios such as heavy read operations or frequent tree manipulations.

By implementing these strategies, backend APIs can efficiently handle nested comments, providing users with a seamless and optimized commenting experience.

Insertion & Deletion of Comments

The circular models of relational databases result in an n-ary tree-based structure, typically associated with O(log(n)) time complexity for insertion and deletion operations. However, circular or self-referential models in relational databases offer optimized performance, allowing for insertion and deletion of comments in O(1) time at the database level.

  • Insertion of Comments

Inserting comments involves adding new comments to a thread or replying to existing comments. At the database level, only the postId and parentId are required for insertion into the table. When commenting on a post, the postId of the thread and the nested level are known. For top-level comments, the parentId is simply null, while for replies, the parentId corresponds to the id of the comment being replied to. This straightforward insertion process does not require traversing the tree and can be accomplished in constant time.

  • Deletion of Comments

Deletion operations exhibit similar performance characteristics. With knowledge of the id of the comment to be deleted, the comment is swiftly removed from the table without the need for tree traversal.

By leveraging the optimized performance of circular models in relational databases, insertion and deletion of comments can be executed efficiently, contributing to a seamless user experience.

Frontend

Top Ten Front-end Design Tips | Toptal®

Frontend implementation of deeply nested comments varies across platforms, presenting unique challenges and requiring different approaches for web and mobile devices. Given the complexity involved, detailed discussion of frontend UI implementation will be covered in a separate blog. In web development, leveraging a declarative approach may aid in handling complex UI requirements, while in mobile development, especially Android, implementing deeply nested behavior within a RecyclerView poses significant challenges, which will be explored in the frontend blog.

I've implemented the deeply nested comments architecture using Django and Android, but the approach remains consistent across other backend frameworks in terms of API logic. Similarly, the declarative UI approach in web frontend development simplifies the implementation process.

By understanding the underlying principles and design considerations discussed in this blog, developers can effectively implement and optimize deeply nested comments architecture across various platforms and frameworks.

Conclusion

This blog has aimed to delve into the architectural aspects of implementing deeply nested comments behavior, inspired by the structures found in platforms like Facebook or Reddit. By exploring the backend logic and considerations for database design, as well as discussing the challenges and strategies for frontend implementation, we've aimed to provide a comprehensive overview of the intricacies involved in handling nested comments.

Through this exploration, developers can gain insights into the complexities of managing hierarchical data structures and learn effective strategies for optimizing performance and user experience.

While this blog focuses primarily on the architecture behind deeply nested comments, it sets the stage for further discussions on frontend UI implementation and additional optimization techniques in future articles.

By understanding the fundamental principles discussed here, developers can embark on their journey to building robust and scalable comment systems, enriching the user experience in their applications.

2
Subscribe to my newsletter

Read articles from Ijlal Ahmad directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ijlal Ahmad
Ijlal Ahmad

Android enthusiast turned full-stack web & Android dev! My 6+ years journey started with Android, but curiosity led me to backend & DevOps via an internship. There, I built email/push services & a cloud storage solution, fueling my passion for web dev. Landing the Smart India Hackathon win for an AI-powered proctored exam tool solidified my expertise. Now, I'm embracing cross-platform development & DevOps tools like Docker & CI/CD, while expanding my AWS knowledge to make a bigger impact. Always learning, always growing, always seeking new challenges!