diff --git a/content/notes/demo.md b/content/notes/demo.md deleted file mode 100644 index 09cbd4f..0000000 --- a/content/notes/demo.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: "Sample Note" -date: 2025-08-20 -# summary: "This is a sample note to demonstrate the notes section" -tags: ["example"] -draft: false ---- - -This is a sample note. Notes are meant to be short, quick thoughts or TILs (Today I Learned). - -Delete this file and add your own notes here! diff --git a/content/posts/my-first-post.md b/content/posts/my-first-post.md deleted file mode 100644 index 1ea5689..0000000 --- a/content/posts/my-first-post.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "The Art of the Digital Garden" -date: 2026-04-01T08:55:00+05:45 -draft: false -tags: ["philosophy", "gruvbox", "hugo"] -description: "Exploring the concept of a digital garden and how a refined Gruvbox theme enhances the experience." ---- - -Welcome to my digital garden. This is a place where I share my thoughts, projects, and lessons learned along the way. Unlike a traditional blog, a digital garden is always growing and evolving. - -### Why Gruvbox? - -Gruvbox is more than just a color scheme; it's a philosophy of contrast and harmony. By using the "Hard" contrast variant, we achieve a focus that is both easy on the eyes and aesthetically pleasing. - -```javascript -const theme = "Gruvbox Dark Hard"; -console.log(`Current theme: ${theme}`); -``` - -### The Beauty of Hugo - -Hugo allows for lightning-fast build times and complete control over the structure of our content. Paired with a minimal theme like PaperMod, it provides the perfect canvas for technical writing. - -> "A garden is never finished." - -I hope you enjoy exploring these notes and posts as much as I enjoy writing them. diff --git a/content/posts/polymorphic-table-psql.md b/content/posts/polymorphic-table-psql.md new file mode 100644 index 0000000..f15072f --- /dev/null +++ b/content/posts/polymorphic-table-psql.md @@ -0,0 +1,105 @@ +--- +title: "The Likes Table Problem: Why We Went Polymorphic." +date: 2026-04-01T21:50:00+05:45 +draft: false +tags: ["architecture", "backend", "PSQL"] +description: "Concept of polymorphic table in an SQL database" +--- + +A few days ago, I was working on adding a **Community** section to an application. The idea was simple, users should be able to: + +- Create posts +- Leave comments +- Like posts +- Like comments + +We also had a separate News section. The new requirement was users should be able to like news articles as well. + +Building model for `posts` and `comments` was pretty straight forward. The real challenge was to model the`likes`table. + +## The Problem: How Do We Store Likes? + +We’re using PostgreSQL, so enforcing relationships with foreign keys is easy and clean. + +If only **one** thing could be liked (say, News), the schema would be simple, we would have a `news_like` table which could look something like this: + +| user_id | news_id | timestamp | +| --- | --- | --- | +| (foreign key) | (foreign key) | 1775059642 | + +But we didn’t have one entity. We had three. `posts`, `comments` and `news`. + +We had to decide: + +> Do we create three separate like tables? Or do we design one flexible solution? + + +## Option 1: Three Separate Tables + +We could create three tables: `post_likes` , `comment_likes` and `news_likes` . Each table would have proper foreign key relationships. This approach would be a clean relational way of doing things. It: + +- Keeps strong relational integrity +- Makes joins easy +- Keeps structure explicit + +This is the most “pure relational” approach. But it felt repetitive. The schema grows horizontally. + +And if tomorrow we add something else that can be liked, we’d need yet another table. + +It works, but it doesn’t scale elegantly. + +## Option 2: A Polymorphic Table (What We Chose) + +Instead of multiple tables, we created a **single polymorphic likes table**. + +### What is a Polymorphic Table? + +A polymorphic table can reference multiple types of resources using a shared structure. + +We designed our `likes` table to look something like this: + +| user_id | resource_id | resource_type | timestamp | +| --- | --- | --- | --- | +| (foreign key) | (uuid) | (POST / COMMENT / NEWS) | | + +Here’s how it works: + +- `user_id`: who liked, foreign key to `users` table. +- `resource_id` : the UUID of the item, just the uuid, no foreign key relation. +- `resource_type` : what type of item it is +- `timestamp` : timestamp + +Instead of a strict foreign key to one table, we store: + +- The ID +- The type of resource + +Together, they uniquely identify what was liked. + +With this approach, we had one clean and centralized table to store all kinds of likes. It’s much easier to expand and flexible. Since “like” is a feature common to many parts of the system, this design keeps it generic and reusable. + +But it does has a major downside. We lose direct foreign key enforcement on `resource_id`. Because PostgreSQL can’t enforce a foreign key that dynamically points to multiple tables, referential integrity must be handled at the application level. We cannot write a simple join query to join from `comments` table or `posts` table. + +For example, to fetch likes for a resource: + +```tsx +SELECT COUNT(*) +FROM likes +WHERE resource_id = 'some-uuid' +AND resource_type = 'POST'; +``` + +Now, if we need resource details plus likes, we may need separate queries or application-side logic. + +For our use case though, that trade-off was acceptable. We don’t perform heavy cross-entity joins on likes, so the downside was minimal. + +## Why This Design Felt Right + +The key insight was this: + +> “Like” is not tightly coupled to Posts, Comments, or News. It’s a behavior shared across resources. +> + +By modeling it polymorphically, we treated “like” as a reusable system capability rather than a feature embedded in each entity. + +And as our application grows, this decision will likely save us refactoring time.