All posts

Fix Memory Leak in Django

Identify and resolve memory leaks in Django applications caused by querysets, caching, signals, and debug mode in production.

Memory Leaks in Django

Django's ORM, signal system, and middleware can all contribute to memory growth that eventually crashes your workers. Here are the most common leaks and their fixes.

DEBUG = True in Production

The number one cause. When DEBUG = True, Django stores every SQL query in django.db.connection.queries:

# settings.py — MUST be False in production
DEBUG = False

Unbounded QuerySet Iteration

Loading millions of rows into memory:

# BAD — loads all objects at once
for obj in MyModel.objects.all():
    process(obj)

# GOOD — use iterator with chunk_size
for obj in MyModel.objects.all().iterator(chunk_size=1000):
    process(obj)

Signals Accumulating Handlers

If you connect signals in a function that runs repeatedly without dispatch_uid:

# BAD — adds a new handler every time
post_save.connect(my_handler, sender=MyModel)

# GOOD — deduplicates with dispatch_uid
post_save.connect(my_handler, sender=MyModel, dispatch_uid='my_unique_handler')

Middleware Storing Per-Request Data

class LeakyMiddleware:
    _cache = {}  # Class-level dict grows forever

    def __call__(self, request):
        self._cache[request.path] = datetime.now()  # Never cleaned

Fix by using Django's cache framework or per-request storage.

Detecting Leaks

Use tracemalloc to find the source:

import tracemalloc
tracemalloc.start()
# ... run your code ...
snapshot = tracemalloc.take_snapshot()
for stat in snapshot.statistics('lineno')[:10]:
    print(stat)

Bugsly tracks memory usage over time, alerting you when a Django worker's memory consumption trends upward — catching leaks before they cause OOM kills.

Try Bugsly Free

AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.

Get Started Free