What Happens as Usage and Data Grow
Last updated:
Data volume, not user count
Django applications rarely slow down because of concurrent users. They slow down because a query that scanned ten thousand rows now scans a million.
Applications frequently get slower with no change in usage at all, purely because the data grew past what the original queries assumed.
The order of work
- Fix query multiplication — lazy loading in loops
- Add missing indexes on filtered and joined columns
- Move reporting to a replica or aggregate tables
- Cache what remains genuinely expensive
- Then add capacity, if still needed
Archive what is no longer in use
Most business applications keep everything indefinitely because nobody decided otherwise. Moving old records out keeps the working set small and every query fast.
It also makes backups faster and restores quicker, which matters more than it sounds during an incident.
Then horizontal capacity
| Step | When |
|---|---|
| Bigger server | Simplest, works for a long time |
| Read replica | Reporting affecting the application |
| Multiple application servers | Concurrency limits reached |
| Separate workers | Background work competing with web |
| Sharding | Rarely, and it is a large step |
Watch the connection pool
Application server processes multiplied by connection pool size must stay within the database's connection limit. Exceeding it under load produces confusing intermittent failures.
It is a simple calculation and it is frequently the cause of problems that look like something more complicated.
Frequently asked questions
How many users can Django handle?
Will moving to the cloud help?
When do we need a read replica?
Is archiving worth it?
Application getting slower as data grows?
That is queries and indexes, not capacity. Happy to find where the time goes.
Related services
What we build for problems like this one