> ## 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.

# Flask - Caching

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

## Flask-Caching with Redis

You can use the Flask-Caching extension with a Flask app deployed on Sevalla by connecting a Redis service to your application.

### Install

To use the caching extension, both Flask-Caching and Redis need to be installed.

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

### Code

The extension needs to be instantiated inside of `extensions.py`.

```python theme={null}
# extensions.py
from flask_alembic import Alembic
from flask_sqlalchemy_lite import SQLAlchemy
from flask_caching import Cache # [!code ++]

from .models import Base

db = SQLAlchemy()
alembic = Alembic(metadatas=Base.metadata)
cache = Cache() # [!code ++]
```

And initialized in `__init__.py`.

```python theme={null}
# init.py
from flask import Flask

from .extensions import db, alembic, cache # [!code ++]

def create_app():
    app = Flask(__name__)
    app.config.from_prefixed_env()

    db.init_app(app)
    alembic.init_app(app)
    cache.init_app(app) # [!code ++]

    return app
```

If you want to use caching in your local environment, add the `FLASK_CACHE_TYPE` and `FLASK_CACHE_REDIS_URL` values to your `.env` file.

```shellsession theme={null}
# .env
FLASK_CACHE_TYPE=RedisCache
FLASK_CACHE_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 change the `REDIS_URL` environment variable to `FLASK_CACHE_REDIS_URL` and add it to the application.

You also need to add the environment variable `FLASK_CACHE_TYPE` with the value `RedisCache`.

### Example

To cache a route, use the `cache` object to decorate the route with `@cache.cached()`. This example caches the route for two minutes.

```python theme={null}
# app/__init__.py
from datetime import datetime
from flask import Flask

from .extensions import db, alembic, cache

def create_app():
    app = Flask(__name__)
    app.config.from_prefixed_env()

    db.init_app(app)
    alembic.init_app(app)
    cache.init_app(app)

    @app.route("/cached") # [!code ++:4]
    @cache.cached(timeout=60 * 2)
    def cached_view():
        return f"Cached at {datetime.now()} for two minutes"

    return app
```

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

Flask-Caching can also be used with the same configuration to cache both templates and regular functions in your app.

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

## CDN

Since static files are served by the Flask app when using `url_for('static')`, you can [enable the CDN setting](https://docs.sevalla.com/applications/cdn#enable-or-disable-sevalla%E2%80%99s-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 route's response to have `response.cache_control.no_store = True`

```python theme={null}
from datetime import datetime # [!code ++]
from flask import Flask, make_response # [!code ++]

from .extensions import db, alembic

def create_app():
    app = Flask(__name__)
    app.config.from_prefixed_env()

    db.init_app(app)
    alembic.init_app(app)

    @app.route("/") # [!code ++:5]
    def index():
        response = make_response(f"Last generated at {datetime.now()}")
        response.cache_control.no_store = True
        return response

    return app
```

To control how long a page will remain in the cache, you need to set the `response.cache_control.max_age` value.

```python theme={null}
from datetime import datetime
from flask import Flask, make_response

from .extensions import db, alembic

def create_app():
    app = Flask(__name__)
    app.config.from_prefixed_env()

    db.init_app(app)
    alembic.init_app(app)

    @app.route("/")
    def index():
        response = make_response(f"Last generated at {datetime.now()}")
        response.cache_control.no_store = True
        return response
    
    @app.route("/page") # [!code ++:5]
    def page():
        response = make_response(f"Cached at {datetime.now()} for two minutes")
        response.cache_control.max_age = 60*2
        return response

    return app
```

Instead of configuring caching directly within individual routes, you can apply caching more globally by using the `after_request` decorator or by creating a custom decorator. This approach helps keep your route handlers clean and makes it easier to apply consistent caching behavior across multiple endpoints.

To verify your pages are being cached correctly, request a page 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.
