Skip to content

First Steps

Let's start with a simple example that shows how to add FastAPI Guard to your application.

Create a FastAPI application

First, create a new FastAPI application:

from fastapi import FastAPI
from guard import SecurityMiddleware, SecurityConfig, IPInfoManager

app = FastAPI()

Configure Security Settings

Create a SecurityConfig instance with your desired settings:

config = SecurityConfig(
    geo_ip_handler=IPInfoManager("your_ipinfo_token_here"),  # NOTE: Required for geolocation
    db_path="data/ipinfo/country_asn.mmdb",  # Optional, default: ./data/ipinfo/country_asn.mmdb
    enable_redis=True,  # Enable Redis integration
    redis_url="redis://localhost:6379",  # Redis URL
    rate_limit=100,  # Max requests per minute
    auto_ban_threshold=5,  # Ban after 5 suspicious requests
    custom_log_file="security.log"  # Custom log file
)

Note: FastAPI Guard only loads resources as needed. The IPInfo database is only downloaded when country filtering is configured, and cloud IP ranges are only fetched when cloud provider blocking is enabled.


Add the Middleware

Add the security middleware to your application:

app.add_middleware(SecurityMiddleware, config=config)

Complete Example

Here's a complete example showing basic usage:

from fastapi import FastAPI
from guard import SecurityMiddleware, SecurityConfig, IPInfoManager

app = FastAPI()

config = SecurityConfig(
    geo_ip_handler=IPInfoManager("your_ipinfo_token_here"),
    enable_redis=True,  # Redis enabled
    redis_url="redis://localhost:6379",
    whitelist=["192.168.1.1", "2001:db8::1"],
    blacklist=["10.0.0.1", "2001:db8::2"],
    blocked_countries=["AR", "IT"],
    rate_limit=100,
    custom_log_file="security.log"
)

app.add_middleware(SecurityMiddleware, config=config)

@app.get("/")
async def root():
    return {"message": "Hello World"}

Run the Application

Run your application using uvicorn:

uvicorn main:app --reload

Your API is now protected by FastAPI Guard! 🛡️


Eager initialization with FastAPI lifespan

Without lifespan wiring, fastapi-guard initializes lazily on the first request — the Redis connection, cloud-IP fetches, pipeline build, and agent / OTEL / Logfire startup all happen there. The first caller pays the full initialization cost.

With guard_lifespan, all of that work runs at ASGI startup, and the first request hits a pre-warmed middleware:

from fastapi import FastAPI
from guard.lifespan import guard_lifespan
from guard.middleware import SecurityMiddleware
from guard_core.models import SecurityConfig

config = SecurityConfig(enable_redis=True, redis_url="redis://localhost:6379")

app = FastAPI(lifespan=guard_lifespan)
app.add_middleware(SecurityMiddleware, config=config)

If you already have a custom lifespan, compose them with make_lifespan:

from contextlib import asynccontextmanager

from guard.lifespan import make_lifespan


@asynccontextmanager
async def my_lifespan(app):
    # your startup work
    yield
    # your shutdown work


app = FastAPI(lifespan=make_lifespan(my_lifespan))
app.add_middleware(SecurityMiddleware, config=config)

OTEL and Logfire users benefit the most: without the lifespan helper their providers initialize on the first request; with it, providers are set at app boot, and the shared-state registry guarantees no duplicate set_tracer_provider call from the spawned-vs-live instance mismatch.


What's Next