# What are your go-to tricks for speeding up a Django test suite?

**URL:** <https://forum.djangoproject.com/t/what-are-your-go-to-tricks-for-speeding-up-a-django-test-suite/45552>\
**Category:** Using Django\
**Created:** [July 23, 2026, 2:56pm UTC](https://forum.djangoproject.com/t/what-are-your-go-to-tricks-for-speeding-up-a-django-test-suite/45552 "2026-07-23T14:56:29Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![sai-dev](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/sai-dev/32/32896_2.png) [@sai-dev](https://forum.djangoproject.com/u/sai-dev)\
**Post date:** [July 23, 2026, 2:56pm UTC](https://forum.djangoproject.com/t/what-are-your-go-to-tricks-for-speeding-up-a-django-test-suite/45552/1 "2026-07-23T14:56:29Z")

</div>

Hey everyone,

As our codebase has grown, our Django test suite execution time has slowed down significantly, and it’s starting to bottleneck our local feedback loops and CI/CD pipelines.

We are already using two major optimization strategies:

1. Running our test cases in **8 parallel processes** (`--parallel=8`).

2. Using **FactoryBoy** for handling ORM setup more efficiently than standard Django fixtures.

Even with these, the suite is sluggish. We want to implement deeper, structural optimizations. What are your go-to advanced strategies for squeezing extra speed out of a growing Django test suite?

---

<div class="post-metadata">

**Author:** ![nanorepublica](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/nanorepublica/32/14211_2.png) [@nanorepublica](https://forum.djangoproject.com/u/nanorepublica)\
**Post date:** [July 23, 2026, 2:59pm UTC](https://forum.djangoproject.com/t/what-are-your-go-to-tricks-for-speeding-up-a-django-test-suite/45552/2 "2026-07-23T14:59:22Z")

</div>

My default would be to recommend Adam Johnson’s book: [Speed Up Your Django Tests](https://adamchainz.gumroad.com/l/suydt)

---

<div class="post-metadata">

**Author:** ![stribny](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/stribny/32/5592_2.png) [@stribny](https://forum.djangoproject.com/u/stribny)\
**Post date:** [July 23, 2026, 3:01pm UTC](https://forum.djangoproject.com/t/what-are-your-go-to-tricks-for-speeding-up-a-django-test-suite/45552/3 "2026-07-23T15:01:47Z")

</div>

Two things from top of my head:

- Skip migrations during test setup (aka don’t let Django execute all migrations one by one, but rather reconstruct final db directly)
- Don’t sleep on durability settings for your database, e.g. for Postgres you can make like 30 % speedup just from good db settings: [Less durability = faster tests - by Petr Stribny](https://devtips.stribny.name/p/less-durability-faster-tests)

---

<div class="post-metadata">

**Author:** ![louzolo123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/louzolo123/32/32811_2.png) [@louzolo123](https://forum.djangoproject.com/u/louzolo123)\
**Post date:** [July 23, 2026, 9:31pm UTC](https://forum.djangoproject.com/t/what-are-your-go-to-tricks-for-speeding-up-a-django-test-suite/45552/4 "2026-07-23T21:31:23Z")

</div>

Hi how’re you feeling chief?  
Great question here are the structural optimizations that usually give the biggest wins on a large Django suite, roughly in order of impact:

1. keepdb (huge, often overlooked)  
Recreating the test database and re-running all migrations on every run is expensive. Reuse it:

python3 manage.py test --parallel=8 --keepdb

Combine it with disabling migrations entirely for tests build the schema straight from the models instead of replaying migration history:

settings/test.py  
class DisableMigrations:  
def **contains** (self, item): return True  
def **getitem** (self, item): return None

MIGRATION\_MODULES = DisableMigrations()

1. Use a fast password hasher  
Argon2/bcrypt are intentionally slow. Any test that creates a user pays that cost:

PASSWORD\_HASHERS = [“django.contrib.auth.hashers.MD5PasswordHasher”]

This alone can shave a surprising amount off auth-heavy suites.

1. setUpTestData instead of setUp  
setUp runs before every test. setUpTestData runs once per class and is wrapped in a transaction rolled back between tests so shared read-only fixtures are created a single time:

class OrderTests(TestCase):  
@classmethod  
def setUpTestData(cls):  
cls.customer = CustomerFactory()

1. Prefer TestCase over TransactionTestCase  
TestCase wraps each test in a transaction and rolls back far faster than truncating tables. Only use TransactionTestCase when you genuinely need to test transaction behavior.

2. Tighten FactoryBoy usage

- Use .build() (no DB hit) instead of .create() whenever you don’t need persistence.
- Watch out for SubFactory chains silently creating deep object graphs — pass existing instances instead.
- Use django\_get\_or\_create to avoid redundant inserts.

1. Profile before optimizing further  
Find the actual offenders rather than guessing:

with pytest-django  
pytest --durations=20

or django-slowtests for the vanilla runner. Often 10% of the tests eat 80% of the time.

1. Mock external I/O  
Any real network/API/filesystem call in a test is a hidden slowdown (and a flakiness source). Mock them.

2. Split the suite  
Fast unit tests for the local loop, slower integration tests gated in CI. Devs get feedback in seconds; the full run happens off the critical path.

One caveat on parallelism: --parallel=8 only helps up to your available cores — going past physical CPUs can slow things down from context-switching, so benchmark it.
