Skip to content

Advanced Usage

This section covers advanced usage patterns and integration scenarios for the FastAPI Maintenance package. These advanced usage patterns demonstrate how FastAPI Maintenance can be integrated into complex systems and workflows.

Combining Multiple Features

You can combine various features of FastAPI Maintenance for sophisticated maintenance scenarios:

from fastapi import FastAPI, Request, Depends
from fastapi.responses import JSONResponse
from fastapi_maintenance import (
    MaintenanceModeMiddleware,
    configure_backend,
    force_maintenance_mode_off,
    maintenance_mode_on
)

# Configure a writable backend
configure_backend("file", file_path="maintenance_mode.txt")

app = FastAPI()

# Custom response handler
async def custom_response(request: Request) -> JSONResponse:
    return JSONResponse(
        content={
            "status": "maintenance",
            "message": "We're upgrading our systems. Please try again later.",
            "estimated_completion": "30 minutes"
        },
        status_code=503,
        headers={"Retry-After": "1800"}
    )

# Custom exemption handler
def is_exempt(request: Request) -> bool:
    # Allow monitoring tools
    if request.headers.get("User-Agent", "").startswith("Monitoring"):
        return True
    return False

# Add middleware with custom handlers
app.add_middleware(
    MaintenanceModeMiddleware,
    response_handler=custom_response,
    exempt_handler=is_exempt
)

# Admin API with decorator-based exemption
@app.post("/admin/maintenance/update")
@force_maintenance_mode_off
async def update_system():
    async with maintenance_mode_on():
        # Perform system update
        await perform_update()
    return {"status": "updated"}

Application Startup and Shutdown

You can use FastAPI's events to configure maintenance mode during application startup and shutdown:

from fastapi import FastAPI
from fastapi_maintenance import (
    MaintenanceModeMiddleware,
    configure_backend,
    set_maintenance_mode
)

# Configure backend
configure_backend("file", file_path="maintenance_mode.txt")

app = FastAPI()
app.add_middleware(MaintenanceModeMiddleware)

@app.on_event("startup")
async def startup_event():
    # Clear any maintenance mode from previous crashes on startup
    await set_maintenance_mode(False)

@app.on_event("shutdown")
async def shutdown_event():
    # Enable maintenance mode during shutdown
    await set_maintenance_mode(True)

Integration with Other Middleware

When using FastAPI Maintenance with other middleware, pay attention to the order:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi_maintenance import MaintenanceModeMiddleware

app = FastAPI()

# Add middleware in the desired order (executed from bottom to top)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

app.add_middleware(MaintenanceModeMiddleware)

# Other middleware
# ...

Here, the maintenance middleware will be executed before the CORS middleware, which means maintenance responses will still have proper CORS headers.

Dependency Injection with Maintenance Status

You can create a dependency that checks the maintenance status:

from fastapi import FastAPI, Depends, HTTPException
from fastapi_maintenance import (
    MaintenanceModeMiddleware,
    get_maintenance_mode,
    configure_backend
)

configure_backend("file", file_path="maintenance_mode.txt")

app = FastAPI()
app.add_middleware(MaintenanceModeMiddleware)

async def maintenance_status():
    return await get_maintenance_mode()

async def require_maintenance_off():
    if await get_maintenance_mode():
        raise HTTPException(status_code=503, detail="Service is in maintenance mode")
    return False

@app.get("/status")
async def status(is_maintenance: bool = Depends(maintenance_status)):
    return {"maintenance_mode": is_maintenance}

@app.post("/api/important")
async def important_action(_: bool = Depends(require_maintenance_off)):
    return {"message": "Important action completed"}

Custom Backends with External Services

You can create a custom backend that integrates with external services:

from typing import Optional
import aiohttp
from fastapi_maintenance.backends import BaseStateBackend

class APIBackend(BaseStateBackend):
    """
    Store maintenance mode state in an external API.
    """

    def __init__(self, api_url: str, api_key: Optional[str] = None) -> None:
        self.api_url = api_url
        self._headers = {"Authorization": f"Bearer {api_key}"} if api_key else {}

    async def get_value(self) -> bool:
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{self.api_url}/maintenance", headers=self._headers) as response:
                if response.status == 200:
                    data = await response.json()
                    return self._str_to_bool(str(data.get("active", False)))
                return False

    async def set_value(self, value: bool) -> None:
        async with aiohttp.ClientSession() as session:
            await session.post(
                f"{self.api_url}/maintenance",
                json={"active": value},
                headers=self._headers
            )

Monitoring Maintenance Status

You can expose an endpoint to monitor the current maintenance status:

from fastapi import FastAPI
from fastapi_maintenance import (
    MaintenanceModeMiddleware,
    get_maintenance_mode,
    force_maintenance_mode_off
)

app = FastAPI()
app.add_middleware(MaintenanceModeMiddleware)

@app.get("/api/status", tags=["monitoring"])
@force_maintenance_mode_off
async def get_status():
    is_maintenance = await get_maintenance_mode()

    if is_maintenance:
        return {
            "status": "maintenance",
            "message": "System is undergoing maintenance"
        }
    else:
        return {
            "status": "operational",
            "message": "All systems operational"
        }