Skip to main content

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.
pip install flask-caching redis
pip freeze > requirements.txt

Code

The extension needs to be instantiated inside of extensions.py.
# extensions.py
from flask_alembic import Alembic
from flask_sqlalchemy_lite import SQLAlchemy
from flask_caching import Cache 

from .models import Base

db = SQLAlchemy()
alembic = Alembic(metadatas=Base.metadata)
cache = Cache() 
And initialized in __init__.py.
# init.py
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) 

    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.
# .env
FLASK_CACHE_TYPE=RedisCache
FLASK_CACHE_REDIS_URL=redis://localhost:6379/0
Within Sevalla, you can create a Redis 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.
# 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") 
    @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 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 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
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

    return app
To control how long a page will remain in the cache, you need to set the response.cache_control.max_age value.
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") 
    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.