The Day I Learned Two Brutal Backend Lessons the Hard Way
Most backend bugs don’t announce themselves loudly. They quietly sit in your system… until one day they don’t.
I learned two of these lessons early on one about security, and one about performance. Both are simple in concept, but extremely common in real systems.
1. “How did he update someone else’s ticket?”
We had a basic ticketing system.
Two users:
- Ramesh → working on Ticket A
- Suresh → working on Ticket B
Everything seemed fine… until Ramesh somehow updated Suresh’s ticket.
At first glance, it felt like a bug in the frontend.
It wasn’t.
The issue was simple:
The API trusted the ticket ID coming from the request without properly verifying ownership.
What went wrong?
We were doing this:
“If request is valid, update ticket.”
But we forgot the real question:
“Is this user allowed to update this specific ticket?”
The fix
Never trust client input for access control.
The backend must:
- Extract user identity from the auth token
- Fetch the resource (ticket)
- Validate ownership or permissions
- Only then allow the update
Because:
Authentication tells you who the user is
Authorization tells you what they can touch
And missing authorization is one of the most common real-world security flaws.
2. The silent killer: N+1 queries
Later, another issue appeared — but this one wasn’t about security.
Get Ashish Bhardwaj’s stories in your inbox
Join Medium for free to get updates from this writer.
It was about performance.
A simple API was fetching tickets and their assigned users.
It worked fine in testing.
But in production, it started slowing down.
What was happening?
Instead of:
- 1 query to fetch tickets
- 1 query to fetch related users
We were doing:
1 query + N queries (for each ticket)
This is the classic N+1 query problem.
At small scale? You won’t notice it.
At production scale? It can bring systems to their knees.
The fix
We optimized data fetching by:
- Using JOINs
- Applying eager loading
- Fetching related data in batches instead of per-record calls
The goal was simple:
Reduce database round trips as much as possible.
Final takeaway
These two issues taught me something important:
- Security bugs happen when we trust the client too much
- Performance bugs happen when we underestimate scale
Both are silent at first. Both become expensive later.
And both are completely avoidable if you get the fundamentals right.




