Configurable timeout middleware for FastAPI applications
Project description
FastAPI Timeout Middleware
A configurable timeout middleware for FastAPI applications that automatically handles request timeouts with customizable error responses.
Features
- ⏱️ Configurable timeout duration - Set custom timeout values per application
- 📝 Customizable error responses - Configure status codes, messages, and response format
- 🔧 Multiple integration methods - Use as ASGI middleware or HTTP middleware decorator
- 📊 Processing time tracking - Optional inclusion of actual processing time in timeout responses
- 🎯 Custom timeout handlers - Provide your own timeout response logic
- 🚀 High performance - Minimal overhead using asyncio
- 📚 Type hints included - Full typing support for better IDE integration
Installation
pip install fastapi-timeout
Quick Start
Method 1: ASGI Middleware (Recommended)
from fastapi import FastAPI
from fastapi_timeout import TimeoutMiddleware
app = FastAPI()
# Add timeout middleware with 5 second timeout
app.add_middleware(TimeoutMiddleware, timeout_seconds=5.0)
@app.get("/")
async def root():
return {"message": "Hello World"}
@app.get("/slow")
async def slow_endpoint():
import asyncio
await asyncio.sleep(10) # This will timeout after 5 seconds
return {"message": "This will never be reached"}
Method 2: HTTP Middleware Decorator
from fastapi import FastAPI, Request
from fastapi_timeout import timeout_middleware
app = FastAPI()
@app.middleware("http")
async def add_timeout(request: Request, call_next):
timeout_handler = timeout_middleware(timeout_seconds=5.0)
return await timeout_handler(request, call_next)
Configuration Options
Basic Configuration
app.add_middleware(
TimeoutMiddleware,
timeout_seconds=10.0, # Timeout after 10 seconds
timeout_status_code=503, # Return 503 Service Unavailable
timeout_message="Request timeout", # Custom error message
include_process_time=True # Include processing time in response
)
⚠️ Important: Do not use HTTP status code 408 (Request Timeout) as it causes browsers and HTTP clients to automatically retry requests, which can lead to unexpected behavior and increased server load. Use 504 (Gateway Timeout) or 503 (Service Unavailable) instead.
Advanced Configuration with Custom Handler
from fastapi import Request, Response
from fastapi.responses import JSONResponse
def custom_timeout_handler(request: Request, process_time: float) -> Response:
return JSONResponse(
status_code=503,
content={
"error": "Service temporarily unavailable",
"path": request.url.path,
"method": request.method,
"timeout_duration": process_time,
"retry_after": 60
},
headers={"Retry-After": "60"}
)
app.add_middleware(
TimeoutMiddleware,
timeout_seconds=15.0,
custom_timeout_handler=custom_timeout_handler
)
Response Format
Default Timeout Response
When a request times out, the middleware returns a JSON response:
{
"detail": "Request processing time exceeded limit",
"timeout_seconds": 5.0,
"processing_time": 5.002
}
Customizable Fields
timeout_status_code: HTTP status code (default: 504 Gateway Timeout)- ⚠️ Avoid 408 (Request Timeout) - causes automatic retries in browsers/clients
- Recommended: 504 (Gateway Timeout) or 503 (Service Unavailable)
timeout_message: Error message (default: "Request processing time exceeded limit")include_process_time: Whether to include actual processing time (default: True)
Use Cases
Web APIs with Database Queries
# Prevent hanging database queries
app.add_middleware(TimeoutMiddleware, timeout_seconds=30.0)
Microservices with External Dependencies
# Timeout requests that depend on external services
app.add_middleware(
TimeoutMiddleware,
timeout_seconds=10.0,
timeout_status_code=503,
timeout_message="Service temporarily unavailable"
)
File Upload Endpoints
# Different timeout for file upload routes
from starlette.middleware.base import BaseHTTPMiddleware
class ConditionalTimeoutMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
if request.url.path.startswith("/upload"):
# Longer timeout for uploads
timeout_handler = timeout_middleware(timeout_seconds=60.0)
return await timeout_handler(request, call_next)
else:
# Standard timeout for other endpoints
timeout_handler = timeout_middleware(timeout_seconds=5.0)
return await timeout_handler(request, call_next)
app.add_middleware(ConditionalTimeoutMiddleware)
Testing
The package includes comprehensive tests. To run them:
pip install fastapi-timeout[dev]
pytest
Requirements
- Python 3.7+
- FastAPI 0.65.0+
- Starlette 0.14.0+
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_timeout-0.1.1.post1.tar.gz.
File metadata
- Download URL: fastapi_timeout-0.1.1.post1.tar.gz
- Upload date:
- Size: 9.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a76ee88804168ac2a387ef82fdb4612c03a79586019ac054b10049e1c407ec9
|
|
| MD5 |
3192ca8a3439b487955defa9c818883d
|
|
| BLAKE2b-256 |
36d5eedd956a467ce8e751cccc72eed6ae3ff0bc1cc5201373cd2b6896c5c590
|
File details
Details for the file fastapi_timeout-0.1.1.post1-py3-none-any.whl.
File metadata
- Download URL: fastapi_timeout-0.1.1.post1-py3-none-any.whl
- Upload date:
- Size: 6.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96014e771e4639d6b50e64e1360b1abb0b69c18e6370e86eec697dab1ba073ce
|
|
| MD5 |
52acba670a7e405235cf377bde4357d8
|
|
| BLAKE2b-256 |
2a188827c42620f026faa3ad36d23b1dd15dda3c4a74d454c69830a9cc6e7cff
|