Implement API Caching with Redis, Flask, and Docker [Step-By-Step]
By: Valon Januzaj
Tags: Cache, Programming, Python, Docker, Redis

You want your API to be faster, more consistent, and to reduce the requests to the server? — That’s where caching comes into play. In this article, I will show you how to implement API Caching with Redis on Flask. I am taking Flask as an example here, but the concept about Caching are the same regardless of the technologies.

What’s caching?

Before we move into the practical part about implementing Caching with Redis and Flask, let’s first know what’s caching as a definition and learn it as a concept so you know then what would the use cases be.

Caching is the ability to store copies of frequently accessed data in several places along the request-response path. When a consumer requests a resource representation, the request goes through a cache or a series of caches (local cache, proxy cache, or reverse proxy) toward the service hosting the resource. If any of the caches along the request path has a fresh copy of the requested representation, it uses that copy to satisfy the request. If none of the caches can satisfy the request, the request travels to the service (or origin server as it is formally known). This is well defined with two terminologies, which are cache miss and cache hit.

Cache hit — A cache hit is a state in which data requested for processing by a component or application is found in the cache memory. It is a faster means of delivering data to the processor, as the cache already contains the requested data.

Cache miss — Cache miss is a state where the data requested for processing by a component or application is not found in the cache memory. It causes execution delays by requiring the program or application to fetch the data from other cache levels or the main memory.

As mentioned above, there are several ways to implement caching. That can be on the client-side through Web Caching, on the server-side through Data Caching (Relational Databases, Redis, etc), Application Caching through plugins that get installed on the application (ex: plugins on WordPress). For this tutorial we’re going to use Redis, to save the responses from the API, and then use those responses instead of making the requests to the server to fetch the data.

Flask and Redis — Implementation

Prerequisites:

Docker & Docker-compose

Flask

Python 3.*+

We are going to use docker to isolate our services, and then docker-compose to orchestrate the services together (putting them on the same network, communication between them, environment variables, etc). If you don’t know about Docker, I suggest you refer to the official docs here.

General workflow

Project setup:

Create python virtualenv and install Flask, redis, flask-caching and requests:

$ python -m venv venv

$ source venv/Scripts/activate

$ (venv) pip install Flask redis flask_caching requests

Our application will look something like this:

/root

├── app.py - Application entrypoint

├── config.py - Config file for Flask

├── docker-compose.yml - Docker compose for app and redis

├── Dockerfile - Dockerfile for Flask API

├── .env - Environment variables

So lets go ahead and create files that are necessary for this setup:

$ touch Dockerfile docker-compose.yml .env

$ pip freeze > requirements.txt

$ touch config.py app.py

What we are going to implement?

We are just going to make a simple endpoint which fetches the university data from Hipolabs universities API, and based on the country that we sent as a query parameter, we get a list with the universities for the specified country.

Let’s go ahead and in app.py create an instance of Flask, and use that to create an endpoint that fetches universities data.

So basically, based on the query parameter country it makes the request to the external API and gets back the data in JSON format . Let’s go ahead and try it:

$ export FLASK_APP=app.py # To tell where your flask app lives

$ export FLASK_ENV=development # Set debug mode on

$ flask run

I will be using Postman to make the request because I also want to see the time that my request takes to process.

Testing the endpoint with Postman; fetch all the universities for Germany

Okay, now we see that we have the results, and everything is working fine as excepted. With the red color, you can see the time that it took to get the data from that endpoint. We can try and make the same request several times, and the performance won’t change. That is because we’re always making a new request to the server. Our goal is to minimize this, and as explained at the beginning to make fewer requests to the server. So let’s go ahead and do that.