Users Need to Be Able to Reply
How a “Small” Comment Feature Turned Into a 38-Hour System Design
“Users need to be able to reply.”
That was the ask.
Before that sentence, I genuinely thought this was easy.
Add a column. Link it. Done. Maybe half a day.
After that sentence?
It became a full commenting system rewrite - designed, implemented, and validated by one developer, with no QA, no business analyst, no UI/UX, and no one to bounce ideas off except my own rubber duck.
This post is the reality behind that request.
The Actual Ask (Verbatim)
Admin – Blog > Comments List Page
- Insert a new “Blog” column between Email and Comments
- Display the blog title
- Blog title should be:
- Underlined
- Clickable
- Opens the blog in a new tab
- Rename column “Show Comments” → “Publish”
- Should be able to edit comments
Public Blog Page
- All published comments appear at the bottom with:
- Date & Time
- Name
- Comment
- Any user assigned to the blog should be able to reply
- Replies should display in a nested UX, showing:
- Date & Time
- Author name
On paper, that sounds… reasonable.
In practice, it explodes.
Why This Was Never “Just Add a Column”
The moment you say “reply”, you are no longer dealing with a flat list.
You’ve introduced:
- Parent–child relationships
- Nesting rules
- Ownership
- Edit history
- Deletion strategy
- Public vs admin behavior
- Validation
- Sanitization
- Data integrity
- UX assumptions that were never documented
And none of that existed before.
There was no:
- Comment hierarchy
- Edit tracking
- Soft delete
- Cascade delete
- Reply fetching
- Nested rendering
- Ownership validation
So before a single UI change could safely exist, the entire backend had to grow up.
What Actually Had to Be Built
I ended up writing a full implementation plan - not because I wanted to, but because without one, this turns into production debt instantly.
1. Data Model Changes
Comments needed to understand:
- Who their parent is
- Whether they were edited
- Whether they were deleted
- When those things happened
That meant new fields, defaults, indexes, and backward compatibility so existing comments didn’t break.
2. Repository Layer (Where Reality Lives)
This is where “reply” becomes expensive.
We needed:
- Create replies
- Fetch replies
- Fetch comments with replies
- Edit comments and replies
- Delete comments with cascade
- Soft delete everything
- Update existing queries so deleted replies don’t magically reappear
Aggregation pipelines. $lookup. Filters everywhere.
One missed condition = ghost comments in prod.
3. Service Layer (Where Rules Live)
This is where things get political:
- Can you reply to a deleted comment? (No.)
- Can you edit someone else’s comment? (Depends.)
- What happens if the email doesn’t match?
- What if it’s admin vs public?
- What if the content includes HTML or scripts?
Everything needed:
- Validation
- Ownership checks (email-based, because there’s no auth yet)
- DOMPurify sanitization
- Explicit error messages
This is where bugs hide if you rush.
4. Middleware & Validation
Because letting raw input through is how you end up on Hacker News for the wrong reason.
- Email validation
- Character limits
- Proper Zod error handling (no more JSON.parse(error.message) hacks)
- Consistent behavior across create, update, reply
5. Controllers (Public + Admin)
New endpoints everywhere:
- Create reply
- Edit comment
- Edit reply
- Delete comment (with replies)
- Delete reply
- Fetch replies
- Fetch comments with nested replies
All with:
- Consistent response formats
- Blog existence checks
- Optional ownership enforcement
- Zero UI assumptions baked into the backend
The Irony
The original visible change?
“All published comments should appear at the bottom with replies.”
That’s the last thing that gets built.
Everything before it exists purely so that sentence doesn’t turn into:
- Broken data
- Security issues
- Impossible edge cases
- A rewrite six months later
Time Reality Check
This wasn’t a “small enhancement.”
It was 29–38 hours of work:
All planned and executed solo.
No QA safety net.
No BA clarifying edge cases.
No UX deciding nesting rules.
Just engineering judgment.
The Takeaway
When someone says:
“Users need to be able to reply.”
What they’re really asking for is:
- A hierarchy
- A lifecycle
- A moderation model
- An ownership model
- A deletion strategy
- A future-proof design
Replying is not a feature.
It’s a system.
And systems don’t come from “just add a column.”
They come from slowing down, thinking properly, and building it once - correctly.
That’s what this was.
And just when I thought the nightmare was over, I remembered… this isn’t even visible yet. This glorious 38-hour backend microservice masterpiece now has to be wired into two separate frontends, the customer-facing UI and the merchant-facing UI-two completely separate repositories, two separate builds, two separate sets of edge cases, and yeah, guess who’s doing it all solo. And if anyone dares say, “but you have A.I., bro”… I’ll flip a table so hard it’ll hit the next dimension. A.I. can generate code, but it can’t feel the existential terror of integrating replies and edits into multiple frontends while maintaining sanity.