Understanding the N+1 Problem in Django (And How to Fix It)
One query for the list, N more for the relations. How the N+1 problem sneaks into Django and how select_related and prefetch_related stop it.
Read the original on Medium ↗If you’re working with Django and relational databases, chances are you’ve encountered performance issues caused by the infamous ‘N+1 query problem’. This blog will explain what it is, why it’s a problem, and how you can fix it with Django’s query optimization tools.

The N+1 query problem occurs when Django runs one query to fetch initial data (the “1”) and then N additional queries to fetch related data for each item, leading to poor performance.
§1Let’s dive into it
With models like:
class User(models.Model):
name = models.CharField(max_length=100)
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='orders')
product = models.CharField(max_length=100)§2The Problem
The N+1 query problem typically appears in two scenarios:
§31. Accessing Related Objects in a Loop (One-to-Many)
When you fetch a queryset and then access related objects (like ForeignKey or reverse relationships), Django performs one query for the initial data and one additional query for each related object.
orders = Order.objects.all() # Get all orders from the database.
for order in orders: # For each order...
print(order.user.name)- 1 query for the orders.
- N queries for each order’s related user.
§42. Accessing Reverse Relationships with Multiple Values (Many-to-Many / Reverse ForeignKey)
When you need to access related data in reverse (like ManyToManyField or reverse ForeignKey), Django fetches related objects in a separate query for each parent object.
users = User.objects.all() # 1 query to fetch all users.
for user in users:
orders = user.orders.all() # N queries to fetch orders for each user.- 1 query for the users.
- N queries for each user’s related orders.
§5The Impact of the N+1 Query Problem on Your Django App
- Increased Database Load: More queries consume more resources, slowing down your app.
- Slower Response Time: More queries = higher latency, resulting in a slower user experience.
- Wasted Database Connections: Multiple queries increase connections, which can cause issues.
- Higher Latency with Large Datasets: As data grows, the problem worsens, causing performance bottlenecks.
- Poor Scalability: As your app scales, the N+1 problem slows down performance even more.
§6Solution
§7Solution 1: select_related
select_related is used to fetch related objects in a single query for ForeignKey and OneToOneField relationships by using SQL joins.
orders = Order.objects.select_related('user').all() # 1 query to fetch all orders and their related users.
for order in orders:
print(order.user.name)1 query to fetch both Order and User data
§8Solution 2: prefetch_related
prefetch_related is used for reverse relationships, where you want to fetch related objects in a separate query and link them in Python.
users = User.objects.prefetch_related('orders').all() # 1 query to fetch users + 1 query to fetch all orders.
for user in users:
orders=user.orders.all():2 queries — one for the users and one for their orders.
§9Conclusion: Solving the N+1 Query Problem in Django
The N+1 query problem occurs when your application executes 1 query to fetch the main data and N additional queries to fetch related data for each item. This can lead to inefficiencies, particularly as the dataset grows.
§10How to Solve It
- select_related: Use for ForeignKey and OneToOneField relationships. This method fetches both the main object and related objects in a single query by using SQL joins, reducing the number of queries.
- prefetch_related: Use for reverse relationships or ManyToMany relationships. It executes separate queries to fetch the main data and related objects, but efficiently links them in Python.
By applying select_related and prefetch_related, you can minimize the number of queries and improve the performance of your Django app.
§11Best Practice
- Optimize queries by using select_related for single reference relationships and prefetch_related for collections of related objects. This approach ensures efficient data retrieval and better scalability as your app grows.