Django Tenants Smart Executor
When using django-tenants, running migrations becomes quite a problem time-wise, especially as your list of tenants grows and the number of your apps and models increases. This is the case even if there are actually no migrations to run.
This package provides two methods of speeding up migrations for django-tenants.
- The first method is to skip running the migration on a schema if there are no migrations to run. If there are no migrations to run, the
schema_migratedsignal is still triggered. - The second method is to skip applying the state part of migrations in a schema when running a migration from the other schema. For example, if running a migration in the public schema, applying the tenant app state migrations is not necessary.
Installation
Install using pip (or your package manager of choice):
pip install django-tenants-smart-executor
Skipping schema migration if there are no migrations to run
Configure the GET_EXECUTOR_FUNCTION in your settings.py:
GET_EXECUTOR_FUNCTION = "django_tenants_smart_executor.load_executor"
This will tell django-tenants to use the executor from this package, which will skip the migrations if there is nothing to run.
When you run migrations when all tenants are migrated, the output will look something like this:
$ python manage.py migrate_schemas
No migrations needed for schema public, only triggering signals
No migrations needed for schema test, only triggering signals
The multiprocessing executor is also supported.
$ python manage.py migrate_schemas --executor multiprocessing
No migrations needed for schema public, only triggering signals
No migrations needed for schema test, only triggering signals
Skipping state migration on schema
By default, this functionality is off. If you want to use it, you need to use the GET_EXECUTOR_FUNCTION configuration mentioned above.
There are three possible modes for this functionality, configured by the SMART_EXECUTOR_LIMIT_STATE_TO_SCHEMA setting.
- Full (
full). You can use this if there are no relationships between the public and tenant schemas. - Public (
public). This will skip the state migrations of tenant apps when running on public schema. This is safe to use when there are no relationships from the tenant schema to the public schema. - Tenant (
tenant). This will skip the state migrations of public apps when running on tenant schema. This is safe to use when there are no relationships from the public schema to the tenant schema.
On top of this, you can further configure exceptions with SMART_EXECUTOR_LIMIT_STATE_EXCEPTIONS_MAP. That option should be a dictionary of boolean (whether it's in the tenant schema) to iterables of apps which should be migrated regardless of the mode.
For example, with the following settings, the only public app that will have state migrations applied in the tenant schemas will be account. There will be no state migrations for tenant apps performed in public schema.
SMART_EXECUTOR_LIMIT_STATE_TO_SCHEMA = "full"
SMART_EXECUTOR_LIMIT_STATE_EXCEPTIONS_MAP: dict[bool, set[str]] = {
True: { # in tenant schema, do migrate these public apps
"account",
},
False: set(), # in public schema, there are no exceptions for any tenant apps
}
Then, you will need to replace every single django.db.migrations import with django_tenants_smart_executor.migrations in your migration files. This is to use the modified version which can skip the state migration. All public classes and functions from the module are reexported, so you can do a simple find & replace.
The ruff rule TID251 is useful for enforcing this.
[ruff.lint.flake8-tidy-imports.banned-api]
"django.db.migrations" = { msg = "Use django_tenants_smart_executor.migrations" }
When to use this
Because this option is disabling state operations, you should only run this when applying migrations, not when creating new migrations or linting them using various tools. You may want to only run this in tests to speed up your tests, but in theory applying in production should be fine as well. Definitely do not contigure this to run when running makemigrations.
Metadata
Release files for django-tenants-smart-executor 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_tenants_smart_executor-0.3.1.tar.gz | 8.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_tenants_smart_executor-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.8 kB
Release files / django_tenants_smart_executor-0.3.1.tar.gz
| Download URL | django_tenants_smart_executor-0.3.1.tar.gz |
|---|---|
| Size | 8.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
06611430dfd3065452ca82f80f1061819fcde31bb629458627025334b771feaa
|
|
BLAKE2b-256 checksum How to use checksums |
80c994130a79d01a356fd91afa2444fe055212f1e9d14e64b34e4fa4be6e6499
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / django_tenants_smart_executor-0.3.1-py3-none-any.whl
| Download URL | django_tenants_smart_executor-0.3.1-py3-none-any.whl |
|---|---|
| Size | 10.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4c1ab5a4c1031bc10bce46fdb7424ef32d9aadf3bebf5034a9aa4c70d71cc09d
|
|
BLAKE2b-256 checksum How to use checksums |
19def5179d217372f1aeaeda697a7c9ac6b6ebdfe99417f8e4c3d35bb3ffac48
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency log