Lightweight SQL profiling middleware for FastAPI + SQLAlchemy
Track query count, database time, and total request time per request.
Installation | Quick Start | How It Works | Development
| Capability | Details |
|---|---|
| SQL instrumentation | setup_sql_profiler(engine) hooks into SQLAlchemy engine events (before_cursor_execute / after_cursor_execute) so SQL executed through that engine is captured per request. |
| Request-level metrics | Adds X-DB-Queries, X-DB-Time, and X-Total-Time response headers. |
| Slow query visibility | Logs queries slower than 0.1s to stdout for quick diagnostics. |
| Context isolation | Uses contextvars for per-request query storage. |
| Minimal setup | One profiler setup call + one middleware registration. |
pip install fastapi-silkPyPI: https://pypi.org/project/fastapi-silk/
from fastapi import FastAPI
from sqlalchemy import create_engine, text
from fastapi_silk import SQLDebugMiddleware, setup_sql_profiler, silk_router
app = FastAPI()
engine = create_engine("sqlite:///./app.db")
# Profiles SQL that goes through this engine
setup_sql_profiler(engine)
app.add_middleware(SQLDebugMiddleware)
# For the UI use
app.include_router(silk_router)
@app.get("/health")
def health() -> dict[str, bool]:
with engine.connect() as conn:
conn.execute(text("SELECT 1"))
return {"ok": True}Example response headers:
X-DB-Queries: 1
X-DB-Time: 0.0012s
X-Total-Time: 0.0049s- Use /_silk link to move for docs where you can find all profiling requests with detailed data
flowchart TD
A[Incoming request] --> B[SQLDebugMiddleware starts request timer]
B --> C[Endpoint runs SQL through profiled SQLAlchemy Engine]
C --> D[setup_sql_profiler listeners capture query start/end]
D --> E[Query data stored in request-local context]
E --> F[Middleware sets X-DB-Queries, X-DB-Time, X-Total-Time]
| Item | Requirement |
|---|---|
| Python | >=3.10 (CI runs 3.10 through 3.14) |
| Framework | FastAPI (CI validates minimum + latest) |
| Database layer | SQLAlchemy Engine (CI validates minimum + latest) |
- Use Ruff for linting and formatting.
- Use MyPy (strict mode) for type checks.
- Keep changes small and typed where possible.
Install dev dependencies and run checks:
uv sync --locked --all-extras --dev
make ci
python -m pytestmake ci runs:
- Ruff lint/format checks
- MyPy strict type checks
- Create a branch from
development(for example,feature/<name>orfix/<name>). - Keep the pull request focused on a single change.
- Add or update tests when behavior changes.
- Run checks locally (
make ciandpython -m pytest). - Open a PR with a clear summary of what changed, why, and how it was tested.
FastAPI-Silk focuses on SQL profiling and request timing headers. It does not provide a built-in dashboard UI.
GNU General Public License v3.0 (GPL-3.0). See LICENSE.
