Organise Flask Configurations The Right Way

Search for a command to run...

I started working on an open-source project about a year ago to build an embeddable alternative to Redis in Go. That’s when I started building the EchoVault project. Since then, the project has gained some interest and even a few contributors. This a...

AWS Cognito user pools allow you to manage your app's within the AWS ecosystem. It provides all the basic features you'd expect from an auth system. When I'm building an application on AWS infrastructure, I prefer using Cognito user pools due to its ...

AWS offers an easy way to work with web sockets through the WebSockets API in API Gateway. This article is going to be a short walkthrough on how to get started with WebSocket APIs. Setup This is article is based on a serverless framework project. Yo...

I've previously written an article about basic username/password authentication with AWS Cognito. This article will cover registration and authentication using Google. Cognito offers this functionality built into the hosted-ui. However, if you find ...

Recently, I posted an article about pre signup triggers for AWS Cognito user pools. The article went over setting up pre signup validation using a lambda function. In this article, I'm going to demonstrate how to achieve the same goal, but using the ...


Flask is a handy python micro-framework for developing web applications and APIs. It is definitely my tool of choice when developing smaller web applications.
On occasion, I even use it for larger projects due to the freedom and flexibility it allows in terms of packages/plug-ins. In this article, I will demonstrate how to organise flask configurations.
A lot of times, apart from a development environment, the apps that we work on will have to be deployed to a production environment. A place where they are universally accessible and open to the general public. This environment will need its own configurations such as databases, secret keys, email servers, etc.
In some cases, your project may even have more environments such as testing and staging. The number of environments you have is irrelevant (if you do things the right way), as you will need a different set of configurations for each environment. I hope that you do not wish to run tests on your production database!
To start off, let’s create a simple flask app with one page and set the configurations:
from flask import Flask
app = Flask(__name__)
app.config['APP_ROOT'] = os.path.dirname(os.path.abspath(__file__))
app.config['MONGO_URI'] = "mongo_uri"
app.config['SECRET_KEY'] = "secret_key"
@app.route("/")
def index():
return "Welcome Home!", 200
if __name__ == "__main__":
app.run()
We’ll keep the views simple as our focus in this article is the app configurations. In this example, the app has one page that returns the text “Welcome Home!” to the user’s browser along with an OK status code. However, pay attention to the 2 lines of code after initialising the app object.
These are the app configurations. These are variables we set in order to use throughout our application. in order to access these values, simply reference them by using app.config[key]. This example is simple enough, and it might be sufficient for a simple application that runs on a single environment. However, it is not the most sustainable or scalable method of handling Flask configurations.
Let’s start with the pros of this method:
That’s about it. This is the method that’s taught in most beginner Flask tutorials and I personally don’t see much use for it after that.
As you can see, the cons far outweigh the pros, and there are many more cons we can specify, but I’ll leave it at that because I’m sure the point has been proven. That being said, this method is not sustainable for large projects or projects that are expected to run in multiple environments.
So what are some ways in which we can better organise our application’s configurations in order to avoid the pitfalls listed above? Well, that’s what this article is for! I’m going to describe 2 of my favourite methods of organising configurations.
The first method is to utilise configuration files. In this method, we will have multiple configuration files, one for each environment. These will contain the configurations for that specific environment.
The file should be a .cfg file and its content will be as follows:
MONGO_URI = "environment_mongo_uri"
SECRET_KEY = "environment_secret_key"
Once you’ve created all the relevant files for the relevant environments, you can import them into your app by replacing the app.config lines with:
app.config.from_pyfile('production.cfg')
app.config.from_pyfile('development.cfg')
Note that in this example, the files are loaded in the order specified so if there is a variable defined in both production.cfg and development.cfg, the development.cfg value will override the one specified in production.cfg.
This means that with this method, we have to remove the line importing the development file before pushing the code to production. This seems simple enough and is a better way of organising the files than the beginner’s method, but as you can probably already tell, this will still get tedious if there are more than 2 environments to worry about. It also requires a separate file for each environment.
A clever way of handling multiple environments is by wrapping the configuration imports in a try/except block and then ignoring the environment-specific files from version control. So, in the example above, we would do the following:
app.config.from_pyfile('production.cfg')
try:
app.config.from_pyfile('development.cfg')
except FileNotFoundError:
pass
We then ignore the development.cfg file in version control. This removes the need to manually delete/comment the line that reads the file. In production, the file will not be found, and the application will carry on.
Another way of handling configurations is by using classes. Here, we create a base class defining common configurations and then create classes that inherit from this base class for each of our environments. Ideally, we’d do this in a separate module. The content of the file could be as follows:
class BaseConfig(object):
DEBUG = False
MONGO_URI = "mongo_uri"
class DevelopmentConfig(BaseConfig):
DEBUG = True
MONGO_URI = "development_mongo_uri"
class TestingConfig(BaseConfig):
DEBUG = True
MONGO_URI = "testing_mongo_uri"
class ProductionConfig(BaseConfig):
MONGO_URI = "production_mongo_uri"
As you can see in the example above, we can create as many classes as we need depending on the number of environments we have. In order to use the configurations above, we simply use the following line of code:
app.config.from_object('configmodule.ProductionConfig')
The above line will load the production config. Replace ProductionConfig with the relevant class for a particular environment. You can also create an instance of the object and pass it to app.config.from_object().
These are a couple of ways to handle configurations in Flask that make handling multiple environments a lot less tedious. These are not the ONLY methods though, there is another very handy method: Using environment variables. Be sure to give these a try in your next project, or even your current one. It’s never too late to refactor!
You can check out Flask’s official documentation regarding handling configuration here.