Bird
Raised Fist0
Djangoframework~8 mins

Request/response middleware flow in Django - Performance & Optimization

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Performance: Request/response middleware flow
MEDIUM IMPACT
This concept affects the time it takes for a web request to be processed and the response to be sent back, impacting server response time and perceived page load speed.
Adding custom logic in Django middleware to process requests and responses
Django
class EfficientMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Minimal processing before view
        response = self.get_response(request)
        # Minimal processing after view
        return response
Avoids unnecessary delays and heavy computations, allowing faster request handling.
📈 Performance GainReduces server response time by up to 1 second per request, improving LCP.
Adding custom logic in Django middleware to process requests and responses
Django
class SlowMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        import time
        time.sleep(0.5)  # Simulate slow processing
        response = self.get_response(request)
        time.sleep(0.5)  # Simulate slow processing
        return response
This middleware adds artificial delays on every request and response, blocking the server and increasing response time.
📉 Performance CostBlocks request processing for 1 second per request, increasing LCP and server load.
Performance Comparison
PatternDOM OperationsReflowsPaint CostVerdict
Heavy blocking middleware0 (server-side)0 (server-side)0 (server-side)[X] Bad
Lightweight middleware0 (server-side)0 (server-side)0 (server-side)[OK] Good
Rendering Pipeline
Middleware runs on the server before and after the main view logic. It processes the request, then the response, affecting how quickly the server can send data to the browser.
Request Processing
Response Processing
⚠️ BottleneckHeavy or blocking operations in middleware delay the response stage, increasing server response time.
Core Web Vital Affected
LCP
This concept affects the time it takes for a web request to be processed and the response to be sent back, impacting server response time and perceived page load speed.
Optimization Tips
1Avoid blocking or slow operations in middleware to reduce server response time.
2Keep middleware logic simple and fast to improve Largest Contentful Paint (LCP).
3Use middleware only for essential processing to prevent delaying the request/response cycle.
Performance Quiz - 3 Questions
Test your performance knowledge
How does heavy processing in Django middleware affect page load?
AIt improves client-side interactivity.
BIt reduces browser rendering time.
CIt increases server response time, delaying page load.
DIt decreases network latency.
DevTools: Network
How to check: Open DevTools, go to Network tab, reload the page, and check the Time column for the server response time of the main document.
What to look for: Look for long 'Waiting (TTFB)' times which indicate slow server response possibly caused by middleware delays.

Practice

(1/5)
1. What is the main purpose of middleware in Django's request/response flow?
easy
A. To directly render HTML templates
B. To run code before and after the view processes a request
C. To manage database migrations
D. To handle user authentication only

Solution

  1. Step 1: Understand middleware role

    Middleware runs code before and after views to modify requests or responses.
  2. Step 2: Compare options

    Only To run code before and after the view processes a request describes this behavior; others describe unrelated tasks.
  3. Final Answer:

    To run code before and after the view processes a request -> Option B
  4. Quick Check:

    Middleware = pre/post view code [OK]
Hint: Middleware wraps views to add pre/post processing [OK]
Common Mistakes:
  • Confusing middleware with template rendering
  • Thinking middleware manages database directly
  • Assuming middleware only handles authentication
2. Which of the following is the correct minimal structure of a Django middleware class?
easy
A. def my_middleware(get_response): def middleware(request): return get_response(request) return middleware
B. class MyMiddleware: def process_request(self, request): pass
C. class MyMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response
D. class MyMiddleware: def handle(self, request): return request

Solution

  1. Step 1: Recall Django middleware class pattern

    Middleware must have __init__ with get_response and __call__ with request.
  2. Step 2: Match options to pattern

    Only class MyMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response matches this exact structure; others miss __call__ or use wrong methods.
  3. Final Answer:

    Class with __init__ and __call__ methods -> Option C
  4. Quick Check:

    Middleware class = __init__ + __call__ [OK]
Hint: Middleware class needs __init__ and __call__ methods [OK]
Common Mistakes:
  • Using process_request instead of __call__
  • Defining middleware as a simple function without class
  • Missing get_response parameter in __init__
3. Given this middleware code, what will be printed when a request is processed?
class LogMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        print('Init called')
    def __call__(self, request):
        print('Before view')
        response = self.get_response(request)
        print('After view')
        return response

# Assume this middleware is active and a request comes in
medium
A. Init called\nBefore view\nAfter view
B. Before view\nAfter view\nInit called
C. After view\nBefore view\nInit called
D. Init called only

Solution

  1. Step 1: Understand middleware instantiation

    __init__ runs once when server starts, printing 'Init called'.
  2. Step 2: Trace __call__ during request

    On request, prints 'Before view', calls view, then prints 'After view'.
  3. Final Answer:

    Init called\nBefore view\nAfter view -> Option A
  4. Quick Check:

    Init once, then before/after view prints [OK]
Hint: Init prints once; __call__ prints before and after view [OK]
Common Mistakes:
  • Thinking __init__ runs on every request
  • Mixing order of prints
  • Ignoring that __call__ wraps the view call
4. Identify the error in this middleware code snippet:
class ExampleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    def __call__(self, request):
        response = self.get_response
        return response
medium
A. Missing parentheses when calling get_response in __call__
B. Missing __init__ method
C. Using wrong method name instead of __call__
D. Returning request instead of response

Solution

  1. Step 1: Check __call__ method

    It assigns response = self.get_response without calling it (missing parentheses).
  2. Step 2: Understand consequence

    Without parentheses, response is a function, not a response object, causing errors.
  3. Final Answer:

    Missing parentheses when calling get_response in __call__ -> Option A
  4. Quick Check:

    Call get_response() with () [OK]
Hint: Always call get_response with parentheses in __call__ [OK]
Common Mistakes:
  • Forgetting parentheses on function calls
  • Confusing method names
  • Returning request instead of response
5. You want to add a custom header 'X-Hello: World' to every response using middleware. Which code correctly implements this?
hard
A. class HeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response.header['X-Hello'] = 'World' return response
B. class HeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): request['X-Hello'] = 'World' response = self.get_response(request) return response
C. class HeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response.add_header('X-Hello', 'World') return response
D. class HeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response['X-Hello'] = 'World' return response

Solution

  1. Step 1: Recall how to add headers in Django response

    Response objects support dict-like access to headers: response['Header-Name'] = value.
  2. Step 2: Check options for correct header addition

    class HeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response['X-Hello'] = 'World' return response uses response['X-Hello'] = 'World' correctly after calling get_response.
  3. Final Answer:

    response['X-Hello'] = 'World' after getting the response -> Option D
  4. Quick Check:

    Use response['Header'] = value to add headers [OK]
Hint: Add headers by setting response['Header'] = value after get_response [OK]
Common Mistakes:
  • Trying to add headers to request object
  • Using non-existent add_header method
  • Accessing headers attribute which doesn't exist on response