← Back to Frameworks

Django — Middleware

FrameworksMiddjango

The Question

How does Django middleware work?

What a Strong Answer Covers

  • top-down request
  • bottom-up response
  • "order matters

Senior-Level Answer

Django middleware is a framework of hooks that sits between the WSGI/ASGI server and your view layer. Every HTTP request passes through each active middleware in order before reaching the view, and the response passes back through them in reverse order. This gives you a clean place to implement cross-cutting concerns — authentication, logging, session handling, CSRF protection — without polluting view code.

Middleware is configured in `settings.MIDDLEWARE` as an ordered list of dotted-path strings. Order matters: a middleware earlier in the list wraps all subsequent ones, so `SecurityMiddleware` must come first to enforce HTTPS redirects before anything else runs.

A middleware class implements up to five hook methods. `__init__(self, get_response)` is called once at server startup and receives a callable representing the rest of the middleware chain. `__call__(self, request)` is invoked on every request — you call `self.get_response(request)` to pass control downstream and get a response back, allowing you to modify both sides. The optional `process_view(request, view_func, view_args, view_kwargs)` hook fires after URL resolution but before the view executes, which is where CSRF validation happens. `process_exception(request, exception)` fires if the view raises. `process_template_response(request, response)` fires if the response has a `render()` method.

Django 1.10 introduced the new-style "callable" middleware, replacing the older class-based hooks (`process_request`, `process_response`). The callable style is cleaner because the entire request-response cycle is visible in one `__call__` method rather than split across two methods.

Practical example: a request-timing middleware wraps `get_response` with `time.perf_counter()` calls and appends a `X-Request-Duration` header to every response. Because it lives outside the view, it captures database and template rendering time too.

For async Django (ASGI), middleware must declare `async_capable = True` and implement `async def __call__`. Mixing sync and async middleware in the stack forces Django to run thread-pool adapters, which adds overhead — keep the stack homogeneous when running async workloads.

Common built-in middleware: `SecurityMiddleware` (HTTPS, HSTS, content-type sniffing), `SessionMiddleware`, `AuthenticationMiddleware` (depends on `SessionMiddleware` being earlier), `CsrfViewMiddleware`, `MessageMiddleware`.

What Separates a 2/3 from a 3/3

2/3 — Passing but Incomplete

Explains the request/response wrapping model, describes __call__ and get_response, and mentions that order in MIDDLEWARE list matters.

3/3 — Strong Answer

Covers all five hook methods, explains old-style vs. new-style middleware, addresses async middleware, and gives a concrete example of a custom middleware with real code logic.

Common Mistakes

  • Confusing middleware order — believing the last entry in the list runs first on requests.
  • Forgetting that AuthenticationMiddleware requires SessionMiddleware to appear before it.
  • Writing state into `self` inside `__call__` — middleware instances are singletons shared across requests, causing race conditions under concurrency.
  • Ignoring async compatibility when deploying Django with ASGI — sync middleware in an async stack triggers expensive thread-pool wrapping.

Follow-Up Questions

  • How would you write a middleware that rate-limits requests by IP address? — Discuss storing counters in Redis with TTL, where to return a 429, and thread-safety considerations.
  • What is the difference between middleware and Django signals? — Middleware is synchronous per-request; signals are event-driven and can fire outside the request cycle.
  • How does CsrfViewMiddleware decide whether to exempt a view? — The @csrf_exempt decorator sets a flag on the view function that process_view checks before validating the token.
  • How would you unit test a custom middleware? — Instantiate it with a mock get_response callable; call it with a RequestFactory-built request; assert on the response.

Related Questions

  • FastAPI — Async vs Sync
  • Django — Signals
  • Django — select_related vs prefetch_related
  • SQLAlchemy — Session
  • FastAPI — Pydantic

Can You Explain This Cold?

Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.

Get Graded — Free Assessment
GrindQuestionsAITechnical interview assessment
TermsPrivacyAbout