> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sevalla.com/llms.txt
> Use this file to discover all available pages before exploring further.

# FastAPI - Caching

> This article explains how to set up caching for your FastAPI application in Sevalla.

## FastAPI-Cache using Redis

You can use the FastAPI-Cache library with a FastAPI app deployed on Sevalla by connecting a Redis service to your application.

### Install

To use the caching extension, both FastAPI-Cache and Redis need to be installed.

```shellsession theme={null}
pip install fastapi-cache2 redis
pip freeze > requirements.txt
```

### Code

The library must first be set up as a lifespan function to work with FastAPI. This setup can be added in `main.py`.

```python theme={null}
# app/main.py
from collections.abc import AsyncIterator # [!code ++:5]
from contextlib import asynccontextmanager
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from redis import asyncio as aioredis
from fastapi import FastAPI
from app.core.config import settings

@asynccontextmanager # [!code ++:5]
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
    redis = aioredis.from_url(settings.REDIS_URL)
    FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")
    yield

app = FastAPI() # [!code --]
app = FastAPI(lifespan=lifespan) # [!code ++]
```

You then need to add `REDIS_URL` to `config.py`.

```python theme={null}
# app/core/config.py
from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_file=".env",)

    SQLALCHEMY_DATABASE_URI: str = ""
    REDIS_URL: str = "" # [!code ++]

settings = Settings()
```

If you want to use caching in your local environment, then add `REDIS_URL` to your `.env` file.

```shellsession theme={null}
# .env
SQLALCHEMY_DATABASE_URI=sqlite:///db.sqlite3
REDIS_URL=redis://localhost:6379/0
```

Within Sevalla, you can [create a Redis database](https://docs.sevalla.com/databases/get-started/add-a-database) and connect it to your app. Make sure you add the `REDIS_URL` to your app when you connect the Redis service to it.

### Example

To cache a route, decorate the route with `@cache` decorator. This example caches the route for two minutes.

```python theme={null}
# app/main.py
...
from fastapi import FastAPI # [!code --]
from fastapi import FastAPI, Response # [!code ++]
from app.core.config import settings
from fastapi_cache.decorator import cache # [!code ++:2]
from datetime import datetime
...
app = FastAPI(lifespan=lifespan)

@app.get("/cached") # [!code ++:4]
@cache(expire=120)
def index(response: Response):
    return {"message": f"Last generated at {datetime.now()}"}
```

Navigate to the `cached/` endpoint, the time the view was added to the cache will be displayed until the cache is updated.

FastAPI-Cache can also be used with the same configuration to cache regular functions in your app.

If you want to cache your entire API, consider using edge caching instead.

## CDN

Even though static files aren't typically served from FastAPI, if you happen to serve static files, you can take advantage of CDN caching. To add CDN caching, [enable the CDN setting](https://docs.sevalla.com/applications/cdn#enable-or-disable-sevalla’s-cdn) to cache your static assets on Cloudflare.

To verify your static files are being cached correctly, request a file and inspect the response headers. The `cf-cache-status` header should be either `HIT` or `MISS`. `MISS` should only occur when the file needs to be set or updated in the CDN. `HIT` will be the expected value for most requests.

## Edge caching

If your app primarily serves endpoints with data that doesn’t change frequently, you can use [edge caching](https://docs.sevalla.com/applications/edge-caching#enable-or-disable-edge-caching) to cache the responses. This will apply to your entire app, except for endpoints that explicitly include headers preventing caching, which the edge cache will ignore.

You can prevent caching by updating the endpoint's response to have a `Cache-Control` header with the value `no-store`.

```python theme={null}
# main.py
from fastapi import FastAPI, Response
from app.core.config import settings
from datetime import datetime

app = FastAPI()

@app.get("/")
def index(response: Response):
    response.headers["Cache-Control"] = "no-store"
    return {"message": f"The current time is {datetime.now()}"}
```

To control how long a page will remain in the cache, you need to set the `max-age` value in your `Cache-Control` header.

```python theme={null}
# main.py
from fastapi import FastAPI, Response
from app.core.config import settings
from datetime import datetime

app = FastAPI()

@app.get("/")
def index(response: Response):
    response.headers["Cache-Control"] = "no-store"
    return {"message": f"The current time is {datetime.now()}"}

@app.get("/page") # [!code ++:4]
def page(response: Response):
    response.headers["Cache-Control"] = "max-age=120"
    return {"message": f"The current time is {datetime.now()}"}
```

To verify your endpoints are being cached correctly, request an endpoint and inspect the response headers. The `cf-cache-status` header should be either `HIT` or `MISS`. `MISS` should only occur when the page needs to be set or updated in the CDN. `HIT` will be the expected value for most requests.
