This One FastAPI Middleware Saved Me 100+ Debugging Hours

Discover the simple yet powerful FastAPI middleware that gave me crystal-clear visibility into every request — and saved me over 100 hours…

This One FastAPI Middleware Saved Me 100+ Debugging Hours
Photo by Daniel Peters on Unsplash

I used to spend hours tracing bugs through logs and tangled request chains — until one middleware flipped the script.

This One FastAPI Middleware Saved Me 100+ Debugging Hours

Discover the simple yet powerful FastAPI middleware that gave me crystal-clear visibility into every request — and saved me over 100 hours of painful debugging.

If you’re building APIs with FastAPI and haven’t added custom middleware for logging requests and responses — you’re flying blind.

I learned this the hard way.

After countless hours of chasing vague bug reports, digging through logs, and trying to replicate issues with insufficient data, I finally did something simple — I wrote a FastAPI middleware that logs every request and response in real-time. The result? Over 100 hours of debugging time saved, countless headaches avoided, and way happier stakeholders.

In this post, I’ll show you the exact middleware that saved me, how it works, and why you should add it to every FastAPI project.


The Problem: “It Works on My Machine…”

You know the drill:

“The API is broken.”
“I got a 500 error, not sure why.”
“It worked a few minutes ago.”

Debugging without context is like finding a needle in a haystack — blindfolded.

When errors happen in production, especially under load, you often don’t have access to:

  • The original request body
  • Headers that triggered a specific behavior
  • Response payloads (especially in 500s)
  • Execution times or anomalies

Sure, tools like Sentry, Datadog, or Prometheus can help — but they don’t always tell the full story. What you need is a first-hand account of every request and its outcome.

The Solution: A Simple Logging Middleware

Here’s the middleware that changed everything for me:

# middleware.py 
from starlette.middleware.base import BaseHTTPMiddleware 
from starlette.requests import Request 
import time 
import json 
import logging 
 
logger = logging.getLogger("uvicorn.access") 
 
class LoggingMiddleware(BaseHTTPMiddleware): 
    async def dispatch(self, request: Request, call_next): 
        start_time = time.time() 
 
        request_body = await request.body() 
        method = request.method 
        url = str(request.url) 
        headers = dict(request.headers) 
 
        logger.info(f"[Request] {method} {url}") 
        logger.debug(f"Headers: {headers}") 
        logger.debug(f"Body: {request_body.decode('utf-8', errors='ignore')}") 
 
        try: 
            response = await call_next(request) 
        except Exception as e: 
            logger.exception(f"[Error] {method} {url}: {str(e)}") 
            raise 
 
        process_time = (time.time() - start_time) * 1000 
        logger.info(f"[Response] {method} {url} completed in {process_time:.2f}ms") 
        logger.debug(f"Status: {response.status_code}") 
 
        return response

To use it, simply add it to your FastAPI app:

# app.py 
from fastapi import FastAPI 
from .middleware import LoggingMiddleware 
 
app = FastAPI() 
app.add_middleware(LoggingMiddleware)

What This Middleware Captures

- HTTP method and URL
- Request headers and body
- Response status code
- Execution time in ms
- Errors (with traceback)

With this information, you get an instant replay of what happened — and that is gold when you’re trying to understand weird bugs or edge cases.

Why It Works So Well

The magic is in context.

Every time something breaks, I now have a precise snapshot of:

  • What the user sent
  • How long it took
  • What we returned
  • If we threw an exception, where and why

This not only helps in fixing bugs fast, but also in preventing them. It highlights slow endpoints, bad clients, unusual inputs, and unexpected failures.

Real-Life Wins

Here are just a few examples of what I caught with this middleware:

  • A mobile app sending malformed JSON due to a bad update.
  • An endpoint slowing down intermittently because of a third-party API.
  • A frontend accidentally spamming a POST endpoint 100+ times on one click.
  • A security vulnerability from unvalidated input — caught before exploit.

Every one of these could’ve taken hours to isolate. With logging in place, it took minutes.

Pro Tips

  • Never log sensitive data like passwords or tokens — use redaction or masking.
  • Exclude logs from health checks or static files to reduce noise.
  • Integrate with tools like ELK stack or Datadog for centralized visibility.
  • For high-traffic apps, switch to structured logging (JSON format) and async log handlers.

Final Thoughts

Debugging doesn’t have to be painful.

This one middleware made me a more efficient developer and gave my team incredible visibility into our APIs. It’s lightweight, easy to implement, and it paid for itself within a week.

If you take away just one thing from this article: add a logging middleware today.

It might just save you 100+ hours too.


Like This Post?

If you found this useful, hit the ️clap and follow for more real-world FastAPI tips, dev productivity hacks, and Python performance tricks.

Got questions or ideas? Let’s talk in the comments

Photo by Sorasak on Unsplash