The Case of the Missing Database Index

By ducpm, at: Oct. 29, 2025, 4:25 p.m.

Estimated Reading Time: __READING_TIME__ minutes

The Case of the Missing Database Index
The Case of the Missing Database Index

 

Introduction

 

Your Django app runs smoothly in development. Queries return instantly. But in production, things slow to a crawl. Pages take seconds to load, users complain, and CPU usage spikes.

 

The culprit? A missing database index - an invisible performance killer that hides until traffic grows. At Glinteco, we’ve seen this countless times: apps that scale in users but not in database design.

 

The Scene: The Slow Query

 

A simple query like this runs in milliseconds in dev:

 

BlogPost.objects.filter(author_id=42).order_by('-created_at')

 

But in production, with millions of rows, the same query takes multiple seconds. The database scans the entire table instead of using a shortcut.

 

The missing witness in this crime scene? An index.

 

How the Problem Happens

 

  1. Small Dev Datasets

     

    • Local databases have only a few hundred rows. Performance looks fine
       

  2. Rapid Growth in Production

     

    • As records climb into the millions, queries slow exponentially
       

  3. No Index Strategy

     

    • Developers rely on defaults, forgetting to optimize columns often used in filters or joins
       

  4. Over-Indexing Mistakes

     

    • On the flip side, too many indexes can slow writes and waste storage

 

Debugging the Bottleneck

 

To catch the missing index, developers use database tools:

 

 

PostgreSQL’s documentation provides detailed guidance on reading query plans.

 

The Fix

 

Add Indexes on Common Filters

 

Example
 

CREATE INDEX idx_blogpost_author ON blogpost (author_id);

 

Use Django’s db_index=True

 

author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True)

 

Leverage Composite Indexes

 

For queries filtering on multiple fields.

 

BlogPost.objects.filter(author_id=42, created_at__gte="2025-01-01")

 

Without an index, the database scans the entire blogpost table. With a composite index on (author_id, created_at), the database can jump straight to the right subset.

 

Solution

 

class BlogPost(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        indexes = [
            models.Index(fields=['author', 'created_at']),
        ]

 

Regularly Audit Queries

 

Run query analysis in staging with real data volumes.

 

Avoid Over-Indexing

 

Every index speeds up reads but slows down writes. Strike a balance.

 

More info can be found here: https://testdriven.io/blog/django-db-indexing/

 

Lesson Learned

 

Database indexes are invisible when they’re missing until they bring your system to a halt. The Case of the Missing Index is a reminder that performance isn’t just about code, but about data design at scale.

 

At Glinteco, we help clients across industries design scalable Django and database systems. Whether it’s adding the right index, tuning queries, or building a long-term growth plan, we ensure your application stays fast as it scales.

 

If your app feels sluggish and you can’t find the cause, it might just be a missing index and we know how to find it.

 

Tag list:

Subscribe

Subscribe to our newsletter and never miss out lastest news.