
A Django homepage can return 200 OK while login is failing, Celery is no longer consuming jobs, or a deploy omitted static files. Useful Django uptime monitoring checks one real user path, one dependency-aware endpoint, and every asynchronous process that can fail independently. This guide combines the external setup with the production metrics, queue, database, and deployment signals needed to explain failures.
Map Django failures to checks
| Failure surface | What users see | Best signal |
|---|---|---|
| WSGI or ASGI process | Timeout, 502, or 503 | Public HTTPS check |
| View, template, or middleware | 500 or wrong page | Content-validated route |
| Database or cache | Dynamic routes fail or stall | Readiness endpoint |
| Celery worker or broker | Email and background work stop | Queue latency plus worker heartbeat |
| Celery Beat | Periodic tasks stop | Last-success heartbeat per critical task |
| Static or media storage | Unstyled pages or missing uploads | Known asset check |
| Bad release | Old workers, missing migration, bad settings | Post-deploy smoke test |
Choose the right endpoints
Monitor the public hostname over HTTPS, not a private process port. Start with a representative data-backed view, login or another critical route, a cheap liveness endpoint, a dependency-aware readiness endpoint, and a versioned static asset from the current release.
Return 503 Service Unavailable when readiness fails. Keep responses free of exception text and infrastructure details. A slow optional third-party API should have its own monitor instead of making the load balancer restart healthy Django workers.
Django's official deployment checklist recommends manage.py check --deploy, a production WSGI or ASGI server, tested logging, and DEBUG=False. Run the check in CI; it validates configuration rather than runtime health.
A minimal dependency-aware view can test the database without exposing exceptions:
from django.db import connection
from django.http import JsonResponse
def readiness(request):
try:
with connection.cursor() as cursor:
cursor.execute("SELECT 1")
except Exception:
return JsonResponse({"status": "unhealthy"}, status=503)
return JsonResponse({"status": "healthy"})
Keep this check cheap and reserve deeper dependency diagnostics for internal telemetry. A cache, broker, or external service belongs in readiness only when this instance must not receive traffic without it.
Monitor Celery and scheduled work
An HTTP check cannot prove a Celery task completed. Track worker online/offline and heartbeat events, oldest-message age per queue, failures and retries by task name, broker availability, and last successful completion for scheduled business jobs.
Celery's official monitoring guide documents worker and task events. For a payment sync or report, emit a heartbeat after successful work, not when Beat merely enqueues the task.
Monitor Beat and workers separately so an alert can identify whether scheduling or consumption stopped. A completion heartbeat proves the entire path, while worker online/offline events, queue age, retries, failures, and throughput explain which stage is unhealthy.
Account for runtime and deployment
- WSGI: watch worker count, request queueing, timeouts, and graceful reloads.
- ASGI: test WebSocket or streaming paths separately; Django's ASGI guidance warns against blocking synchronous calls in async code.
- Containers: use cheap liveness for restarts and dependency-aware readiness for traffic routing.
- Multiple process types: expose a non-secret release ID and confirm web and Celery run the same code.
- Static files: check an asset referenced by the current page, not an evergreen file that can survive a failed
collectstatic.
Cover the supporting Django stack
- Database: connection waits, slow queries, storage, migration failures, and replica lag.
- Cache and broker: Redis or Memcached availability, latency, memory pressure, and evictions.
- Static and media: current release assets, CDN or object-storage permissions, and upload retrieval.
- Domain and TLS: DNS targets, redirect behavior, certificate expiry, and chain validity.
- Deployment: migrations,
collectstatic, web-worker restart, Celery restart, release parity, and a post-deploy smoke test.
Different deployment models change where these signals live, not whether they are needed. Gunicorn plus Nginx requires public-path, readiness, current-asset, worker, and Beat checks. Containers should use cheap liveness and traffic-aware readiness. PaaS and autoscaled systems still need external checks because a healthy platform does not prove the application journey works.
Common Django failure patterns
| Failure | User impact | Detection |
|---|---|---|
| Celery worker stopped | Email and background work queue indefinitely | Worker events plus queue age |
| Beat stopped | Periodic tasks are never dispatched | Scheduler signal plus completion heartbeat |
| Database pool exhausted | Intermittent 5xx and request stalls | Pool waits, readiness, and data-backed route |
| Old worker release | Web and jobs disagree about schema or payloads | Release-ID parity check |
collectstatic missed |
Broken CSS or JavaScript | Current fingerprinted asset check |
| Migration missing | Changed code returns 5xx | Post-deploy data-backed smoke test |
| Blocking sync work in ASGI | Streaming or WebSocket paths stall | Path-specific latency and concurrency metrics |
Django monitoring checklist
- Dynamic user path checked over HTTPS with content validation
- Liveness and readiness have different contracts
- Celery worker events and oldest-job age monitored
- Critical periodic jobs report successful completion
- Current static asset checked after every deploy
-
manage.py check --deployruns with production settings - Web and worker release IDs match
- Alerts link to a Django-specific runbook
Page on sustained failure of a customer path, readiness, or critical queue. Warn on latency drift and non-critical delay. See health endpoint design, job queue monitoring, and 5xx alerting.
Webalert can provide the external HTTP, content, response-time, SSL, and heartbeat layer. Start monitoring and pair it with Django and Celery metrics for complete coverage.