Logo Image

Banishing the N+1 Curse: A Hogwarts Tale of select_related() & prefetch_related()


Every time I open that dusty ledger in the Great Hall, I could almost hear the owls, flapping their wings and sounding unhappy. By student fifty, the poor creatures looked like they needed a vacation—and so did my database!

🧙‍♀️ The Lazy Ledger Problem


students = Student.objects.all()            # 1 query to fetch all students
for s in students:
    print(s.house.name)                     # +1 query per student
    print(s.wand.core)                      # +1 query per student
    for spell in s.spells.all():            # +1 query per student for spells…
        print(spell.name)

Picture Professor Summer Sault sitting on her stool, wand at the ready, determined only to list each witch and wizard’s House and Wand core. In practice, she unleashed an avalanche of owl-flights:

By the time she reached the Weasley twins, her ledger—and the owl stable—was groaning under the weight.


✨ One Chant for Houses & Wands: select_related()

Just as Professor Summer Sault was about to send off a dozen's of owls, Professor Autumn Gold swept into the Great Hall and proclaimed:

students = Student.objects.select_related('house', 'wand').all()

“Why send many owls,” she asked, “when one can carry everything at once?”

Behind the scenes, Django weaves a SQL JOIN:

SELECT student.*, house.name, wand.core
FROM student
LEFT JOIN house ON student.house_id = house.id
LEFT JOIN wand  ON student.wand_id  = wand.id;

One query. One fully loaded owl. Zero extra trips.


🧹 Bundling Spells & Friends: prefetch_related()

What happened is that Professor Summer Sault, fresh off her brilliant select_related() success (no more owl-flights for Houses and Wands!), tried to apply the same “one-spell-fits-all” approach to Spells and Friends—but forgot that ManyToMany relations need a different charm. So her next incantation still summoned an owl for each spell:

“I’ll just prefetch all spells the same way…”
poof! — dozen’s of more owl-flights.

Seeing this, Professor Autumn Gold steps forward and waves her wand:

    students = Student.objects.prefetch_related('spells', 'friends').all()

“Why chase each spell one by one,” she called out,
“when you can gather them all at once?”

This time Django casts two nets:

  1. Students:
   SELECT \* FROM student;
  1. Spells & Friends:
   SELECT spell.\*, student_spells.student_id
   FROM spell
   JOIN student_spells ON spell.id = student_spells.spell_id
   WHERE student_spells.student_id IN (...all IDs...);

(And similarly for the friends link table.)

Once those two queries complete, Django automatically attaches each student’s spells and friends to the Student objects in memory. That means:

    for s in students:
        for spell in s.spells.all():  # ZERO new queries here!
            print(spell.name)

Thanks to Professor Winter Sugar’s timely intervention, we get just two owl-flights total—no matter how many students or spells there are.


🎓 Quick-Reference Cheat Sheet select_related()

MethodIdeal forSQL behavior
select_related()ForeignKey / OneToOne fieldsSingle JOIN query
prefetch_related()ManyToMany / reverse FK relations1 base + 1 per relation

Dumbledore’s Dispatch: You can even follow multi-level relations: Book.objects.select_related('authorprofileavatar')


🔮 Epilogue: A Wizard’s Promise

May your queries be swift, your pages be light, and your dev servers run bright every night.

And so, thanks to Professor Summer Sault’s clever join charm and Professor Autumn Gold’s masterful prefetch spell, the Great Hall’s ledger stayed fast and clear—and no witch or wizard ever feared the N+1 Curse again.

About the Author

I’m YashRaj, a Solution Engineer at Hashtrust Technologies, driven by a deep curiosity for AI and how it can reshape everyday problem-solving. My work revolves around experimenting with GenAI tools, building efficient systems, and crafting solutions that are both smart and scalable. I’m always exploring new ways to make technology more intuitive and impactful.

About Hashtrust

Hashtrust is a product engineering and innovation company helping startups and enterprises build intelligent solutions using AI agents, GenAI, and multi-agent systems. From rapid POCs to production-grade platforms, Hashtrust empowers teams to turn ideas into impactful, scalable tech products.

Explore more at hashtrust or reach out at support@hashtrust.in.