Confirm it first by counting queries, using Django Debug Toolbar locally or assertNumQueries in a test. The pattern is a loop touching a related object, which triggers a query per row because querysets are lazy. Fix forward relations with select_related, which does a join, and reverse or many to many relations with prefetch_related, which runs one extra query.
Why interviewers ask this
This is the single most common performance bug in ORM backed applications, so it is close to a job requirement. Interviewers want to see you measure before you optimize, that you understand queryset laziness as the underlying cause, and that you know select_related and prefetch_related solve different relationship shapes. Adding a regression test rather than just patching it is the senior signal.
How to structure your answer
- Say you measure the query count first.
- Explain laziness as the root cause.
- Match select_related and prefetch_related to relation types.
- Lock the fix in with a query count test.
Example answer
Measurement comes first, because guessing at ORM performance is a waste of an afternoon. Locally I turn on the debug toolbar or log queries at debug level, and if it is already in production I look at the trace, where an endpoint firing four hundred nearly identical selects is unmistakable. The cause is that a queryset does not hit the database until you iterate it, and accessing a foreign key on each row lazily fetches that row relation. For a forward foreign key I add select_related, which turns it into a join and one query. For reverse relations or many to many I use prefetch_related, which issues a second query and stitches the results together in Python. Once fixed, I write a test wrapping the view in assertNumQueries with the expected number, because otherwise the next person adds a template field and it regresses silently. On an internal dashboard we took one page from about three hundred queries to four, and load time went from roughly two seconds to under two hundred milliseconds.
Walking into this interview soon? GhostPilot listens to your live call, spots the question the moment it is asked, and puts a structured answer on your screen in real time. Try it on your next mock, or grab a $29 Session Pass, no subscription, for the real thing.
See how it worksFollow-up questions to expect
- When is prefetch_related slower than a join?
- What do only and defer change here?
- How would you catch this in code review?
Related python developer questions
Your interviewer will ask their own version of this. Paste your actual job description into the free Question Predictor and get the 20 questions that role is most likely to ask, with what each one is really probing.
Predict my questions