django-api-usage
Lightweight, privacy-first usage metering for Django APIs, with an optional deprecation lifecycle layer on top.
It answers two questions that decide whether an endpoint can be changed or removed:
- How much is this endpoint (or this whole Django app) used?
- Who is calling it, so they can be contacted before it changes?
The package is deliberately generic: the core is plain Django middleware (works with or without Django REST Framework), it never breaks a request because metering failed, and it stores no raw personal data by default.
Why not just drf-api-tracking?
drf-api-tracking stores one database row per request (including bodies), which
is heavy and privacy-sensitive. django-api-usage accumulates counters and
keeps consumer attribution hashed and opt-in. That makes it suitable both for
continuous usage analytics and for the concrete decision of deprecating an
endpoint.
Install
pip install django-api-usage
INSTALLED_APPS = [
# ...
"django_api_usage",
]
MIDDLEWARE = [
# ...
"django_api_usage.middleware.ApiUsageMiddleware",
]
Metering starts immediately. Counters are buffered in the cache and written to the database in batches:
python manage.py api_usage_flush # from cron, or a Celery beat task
python manage.py api_usage_report --days 30
python manage.py api_usage_report --days 90 --sunset-candidates
With Celery (and the celery extra) two tasks are provided:
django_api_usage.tasks.flush_api_usage and
django_api_usage.tasks.prune_api_usage.
Configuration
API_USAGE = {
"ENABLED": True,
"FAIL_OPEN": True,
"BUFFER_BACKEND": "cache", # "cache" (batched) or "db" (write per request)
"RETENTION_DAYS": 90,
"TRACK_CONSUMERS": False, # opt-in; stores hashed callers only
"CONSUMER_SALT": "a-rotatable-secret",
}
All resolvers are overridable, so no project-specific knowledge leaks into the package:
API_USAGE = {
"APP_LABEL_RESOLVER": "myproject.api.resolvers.app_label",
"SITE_RESOLVER": "myproject.api.resolvers.site_id",
"ROLE_SCOPES_RESOLVER": "myproject.api.resolvers.role_scopes",
}
Deprecation lifecycle
Endpoint carries deprecated, sunset_date, replacement and owner, so the
same data that measures usage also drives a deprecation plan. See the consuming
project's migration guide for the full workflow (measure → notify → enforce).
DRF shadow mode
django_api_usage.drf.HasAPIScope enforces scopes declared on a view:
class AllUserViewSet(viewsets.ReadOnlyModelViewSet):
permission_classes = [HasAPIScope]
required_scopes = ["user:read_all"]
With API_ENFORCEMENT = "report" (the default) nothing is blocked yet: a
X-Api-Would-Deny header is returned instead, so you can deploy a permission and
measure what it would have denied before enforcing it.
Status
Alpha. The core is implemented: metering middleware, models and migrations, management commands, the deprecation layer and a DRF shadow-mode permission. Tested on Python 3.10-3.12 and Django 4.2/5.2. MIT licensed.
Development
python -m django test tests --settings=tests.settings
ruff check .
black --check .
Metadata
Release files for django-api-usage 0.1.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_api_usage-0.1.1.tar.gz | 21.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_api_usage-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.1 kB
Release files / django_api_usage-0.1.1.tar.gz
| Download URL | django_api_usage-0.1.1.tar.gz |
|---|---|
| Size | 21.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
849a616aece81c5e35ae5b7787f4b7607d921efb4156536dd31be6cb79d5d2ed
|
|
BLAKE2b-256 checksum How to use checksums |
3256b839672279ac588d7923faaa7b87515d6eae2a64216524777dbbc3903b61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|
Release files / django_api_usage-0.1.1-py3-none-any.whl
| Download URL | django_api_usage-0.1.1-py3-none-any.whl |
|---|---|
| Size | 22.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6815cdf5035fed8a4aecc64e23968dbbc1c35e93b455764d0998395337011b96
|
|
BLAKE2b-256 checksum How to use checksums |
447d3ecd98d1d21c140ae22dd3d5155386dd0245bb5e82e8b0f1b77afbf67b8e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|