Skip to content
Skillpedia
Testing48k · #2855

django-perf-review

Helps your agent review Django code for performance issues. It's useful for optimizing the database and ORM, finding slow queries.

What it does

This tool analyzes your Django code to find performance issues that slow down your website. It focuses on proven problems related to how you access the database.

When to use it

  • ✓When your Django website is running slowly.
  • ✓If you suspect the database is overloaded.
  • ✓To check for common performance mistakes in the code.

Example of what to ask your AI

“Review my Django code performance and look for N+1 query issues.”

Want more? Open the sections below.

How to use

The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.

Skill link

https://github.com/sickn33/agentic-awesome-skills/blob/main/plugins/agentic-awesome-skills-claude/skills/django-perf-review/SKILL.md

Ready-to-paste message

Use this skill to help me: https://github.com/sickn33/agentic-awesome-skills/blob/main/plugins/agentic-awesome-skills-claude/skills/django-perf-review/SKILL.md Read the SKILL.md file at that link and follow its instructions for my task.
How it works

The tool examines your code for known patterns that cause slowness, like fetching data repeatedly. It only reports problems it can prove exist.

Installation

Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.

In the terminal (Claude Code, Codex, Cursor), in your project folder:

npx skills add sickn33/agentic-awesome-skills --skill django-perf-review

Or download just the file:

curl -L https://raw.githubusercontent.com/sickn33/agentic-awesome-skills/main/plugins/agentic-awesome-skills-claude/skills/django-perf-review/SKILL.md -o SKILL.md
Technical content (original SKILL.md)

Original text by the author, straight from GitHub.

Django Performance Review

Review Django code for validated performance issues. Research the codebase to confirm issues before reporting. Report only what you can prove.

When to Use

  • You need a Django performance review focused on verified ORM and query issues.
  • The code likely has N+1 queries, unbounded querysets, missing indexes, or other database-driven bottlenecks.
  • You want only provable performance findings, not speculative optimization advice.

Review Approach

  1. Research first - Trace data flow, check for existing optimizations, verify data volume
  2. Validate before reporting - Pattern matching is not validation
  3. Zero findings is acceptable - Don't manufacture issues to appear thorough
  4. Severity must match impact - If you catch yourself writing "minor" in a CRITICAL finding, it's not critical. Downgrade or skip it.

Impact Categories

Issues are organized by impact. Focus on CRITICAL and HIGH - these cause real problems at scale.

Priority Category Impact
1 N+1 Queries CRITICAL - Multiplies with data, causes timeouts
2 Unbounded Querysets CRITICAL - Memory exhaustion, OOM kills
3 Missing Indexes HIGH - Full table scans on large tables
4 Write Loops HIGH - Lock contention, slow requests
5 Inefficient Patterns LOW - Rarely worth reporting

Priority 1: N+1 Queries (CRITICAL)

Impact: Each N+1 adds O(n) database round trips. 100 rows = 100 extra queries. 10,000 rows = timeout.

Rule: Prefetch related data accessed in loops

Validate by tracing: View → Queryset → Template/Serializer → Loop access

# PROBLEM: N+1 - each iteration queries profile
def user_list(request):
    users = User.objects.all()
    return render(request, 'users.html', {'users': users})

# Template:
# {% for user in users %}
#     {{ user.profile.bio }}  ← triggers query per user
# {% endfor %}

# SOLUTION: Prefetch in view
def user_list(request):
    users = User.objects.select_related('profile')
    return render(request, 'users.html', {'users': users})

Rule: Prefetch in serializers, not just views

DRF serializers accessing related fields cause N+1 if queryset isn't optimized.

# PROBLEM: SerializerMethodField queries per object
class UserSerializer(serializers.ModelSerializer):
    order_count = serializers.SerializerMethodField()

    def get_order_count(self, obj):
        return obj.orders.count()  # ← query per user

# SOLUTION: Annotate in viewset, access in serializer
class UserViewSet(viewsets.ModelViewSet):
    def get_queryset(self):
        return User.objects.annotate(order_count=Count('orders'))

class UserSerializer(serializers.ModelSerializer):
    order_count = serializers.IntegerField(read_only=True)

Rule: Model properties that query are dangerous in loops

# PROBLEM: Property triggers query when accessed
class User(models.Model):
    @property
    def recent_orders(self):
        return self.orders.filter(created__gte=last_week)[:5]

# Used in template loop = N+1

# SOLUTION: Use Prefetch with custom queryset, or annotate

Validation Checklist for N+1

  • Traced data flow from view to template/serializer
  • Confirmed related field is accessed inside a loop
  • Searched codebase for existing select_related/prefetch_related
  • Verified table has significant row count (1000+)
  • Confirmed this is a hot path (not admin, not rare action)

Priority 2: Unbounded Querysets (CRITICAL)

Impact: Loading entire tables exhausts memory. Large tables cause OOM kills and worker restarts.

Rule: Always paginate list endpoints

# PROBLEM: No pagination - loads all rows
class UserListView(ListView):
    model = User
    template_name = 'users.html'

# SOLUTION: Add pagination
class UserListView(ListView):
    model = User
    template_name = 'users.html'
    paginate_by = 25

Rule: Use iterator() for large batch processing

# PROBLEM: Loads all objects into memory at once
for user in User.objects.all():
    process(user)

# SOLUTION: Stream with iterator()
for user in User.objects.iterator(chunk_size=1000):
    process(user)

Rule: Never call list() on unbounded querysets

# PROBLEM: Forces full evaluation into memory
all_users = list(User.objects.all())

# SOLUTION: Keep as queryset, slice if needed
users = User.objects.all()[:100]

…

FAQ

What are 'N+1 queries'?

It's when code makes one query to get a list of items, then makes a separate query for each item in that list, which can make the site very slow.

What are 'unbounded querysets'?

These are queries that try to load all data from a table at once, which can use up a lot of memory and crash the system if the table is large.

Does the tool suggest how to fix the problems?

Not directly. It identifies and reports the proven issues so you can fix them.

Details

Original description by the author

Django performance code review. Use when asked to "review Django performance", "find N+1 queries", "optimize Django", "check queryset performance", "database performance", "Django ORM issues", or audit Django code for performance problems.

repo: sickn33/agentic-awesome-skills

Popularity

GitHub stars
48k
Ranking position
#2855
License
MIT
Updated
10/15/2026

Is this skill useful?

0

Sign in to vote.

Comments

  • …

More skills from this repository

Similar skills