How I Set Up Database Migrations for my Serverless Flask App Deployed with Zappa
This blog post assumes you are familiar with
My application follows the
create_app pattern outlined in the Flask Flaskr example blog tutorial. Because of this, we need to make some adjustments to the usual deployment process when using Zappa to deploy our application.
Since we cannot call the
create_app() function directly from
__init__.py with Zappa, we will create a supplementary
run.py file that instantiates our app, we will them point to this in
zappa_settings.json. Note that
yt_pubsub_handler is the name of the project. You can see it on GitHub.
We can now point Zappa to this app variable:
Zappa now knows where to look for our app!
If you are not familiar with database migrations, there are generally two options:
upgrade is when you make a new change to your database a structure, and a
downgrade is when you revert that change. We need to be able to do this with our application database that is hosted on aws - but we can only really do this in production, since we don’t want to expose database credentials and permissions to devs. We also would not want to allow anyone to run the changes locally, since they should go through the approval process on GitHub first.
Flask-Migrate exposes a great CLI, but we cannot run CLI commands with Zappa. So we need a workaround - we need to use the
Flask-Migrate API to create some helper functions that will allow us to upgrade and downgrade our database.
Note that I have already Introduced
Flask-Migrate into my
create_app() function and have run
flask db init to generate a
migrations/ folder at the root of my project directory.
Now we need to write some helper functions in order to run the CLI commands
flask db upgrade and
flask db downgrade via Zappa’s python interface.
Notice that these functions take in an
app variable, which is a reference to the Flask
app object itself, that we first instantiated in
run.py. So now we need to access these via the
run.py file so that we can pass that app reference to these functions. Without the
app_context() our functions will not know which database they should be interacting with. Note that
current_app will not work in this scenario. So let’s extend our
Creating a Migration
We can now create a branch and alter our database. To demonstrate, I made a change to
Flask-Migrate automatically picks up.
The flow I use typically includes the following steps:
- Start a local dev session
- Edit the
- Open a second terminal pane, ensure
export FLASK_APP=yt_pubsub_handleris also set here
flask db migrateto automatically create a revision in the
- Review this thoroughly since it is auto-generated and may contain flaws
- Commit changes and open a PR to merge the changes into production
- Once merged and deployed with
zappa update production, execute the migration with:
For downgrade simply replace with
Here we used Flask-Migrate’s API with some additional functionization to work with the Zappa serverless deployment framework. We can now make changes to our application database with ease.