Skip to content

First deploy

Database Instance

The first thing we'll need is a database. subZero service runs in AWS us-east-1 so that's where we'll create our PostgreSQL RDS instance to have low latency between the database and subZero (other regions will be available).

Create the database

To create the database we'll use a handy cloudformation stack that will spin up a free tier RDS instance in your AWS account. Just click the button below and fill in all the fields.


If you prefer to customize the database instance, follow this link to create one. Make sure you select PostgreSQL, make it publicly available and then add a rule in it's security group to allow subzero to connect to it.

Create Stack

The database creation process will take about 5 minutes, so until it's ready you can skip for a moment "connect to the database" part and continue with creating a subzero account the you can come back later to get the connection info for your database.

Connect to the database

When the stack creation completes, click on the Outputs tab where you will find connection information for the database.

Connection Info

Use your preferred PostgreSQL GUI client (ex. DBeaver, Postico) to connect to the database or just use psql in command line (if you don't already have it, it's easy to install).

The database is ready; let's move to the next step.

subZero Account

Go to the signup page and create your account then login. That's all, you don't need to create configure the app from the UI (though you can), we'll have our deploy script do it.

Prepare the migrations folder

During the development process, we worked with files from db/src/ to define our schema. Whenever we changed something, subzero cli dropped and recreated the local development database to reflect those changes, however, when we want to deploy the changes we can not just drop the database since we would lose the data in the tables. This is where the migrations come in. We'll maintain a db/migrations folder that will contain simple sql scripts that migrate our database schema from state A to state B. Don't worry, this process is almost entirely automated, you won't have to create those files manually, they will be created by subzero cli based on the files from db/src/. Let's start the process.

In the root of your project execute

subzero migrations init --with-roles

The output will look similar to this

Created sqitch.conf
Created sqitch.plan
Created deploy/
Created revert/
Created verify/
Starting temporary PostgreSQL database with the version matching your dev database (postgres:13)
on port 42585 with SQL from /db/src
Waiting for temp_postgres_ihmku container to load
PostgreSQL init process complete; ready for start up.
Writing database dump to /db/migrations/tmp/20210223104353-dev-initial.sql
Writing database roles dump to /db/migrations/tmp/20210223104353-dev-initial.sql.roles
Starting temporary PostgreSQL database with the version matching your dev database (postgres:13)
on port 40073 with SQL from /db/migrations/deploy
Waiting for temp_postgres_3i5cg container to load
PostgreSQL init process complete; ready for start up.
Diffing databases using migra
Writing the result to /db/migrations/tmp/20210223104353-revert-initial.sql
Created deploy/20210223104353-initial.sql
Created revert/20210223104353-initial.sql
Created verify/20210223104353-initial.sql
Added "20210223104353-initial" to sqitch.plan
Copying /db/migrations/tmp/20210223104353-dev-initial.sql to /db/migrations/deploy/20210223104353-initial.sql

Commit the changes to git

git add db/migrations/

git commit -m "initial database migration"
git push


A word to the wise
We've chosen to perform the first deploy as a step immediately after setting up our project locally to be able to illustrate later how one would iterate on a project running in production (implement a feature -> push to production). In practice however you want to postpone this first deploy for when you have something closer to an MVP. The reason is that during the early stages you will have a lot of changes in your database schema and it will be a lot of work creating migrations (even though it's mostly automated) for all those changes and checking their correctness. At this stage it's better to avoid having migrations altogether. However, it you still need a common staging deployment until you go to production, we recommend working locally on your application and adapt your deploy script to recreate the db/migrations/ folder each time and reset your test database before deploying the new schema changes.

In a later tutorial, we'll see how we can create a new migrations after we've added a few changes to our database schema

Configure GitHub secrets

subZero's deploy process is implemented using GitHub Actions


If you are interested in the exact deploy steps, look at .github/workflows/test_deploy.yml configuration file.

Create the following encrypted secrets in your github repository (Settings > Secrets > New repository secret). Detailed steps are described here

Name Description
SUBZERO_EMAIL The email you used to create a account
SUBZERO_PASSWORD account password
APP_DOMAIN The desired application domain. For free accounts you can only use subdomains in the form Paid accounts can use their custom domains (that they control), for example
APP_DB_HOST Production database host name (or IP)
APP_DB_PORT Database port (usually it's 5432)
APP_DB_NAME The database name
APP_DB_MASTER_USER Database user with SUPERUSER privileges. This user is only used by the deploy scripts to deploy the database migrations, It's not sent or stored in
APP_DB_MASTER_PASSWORD Master user password
APP_DB_AUTHENTICATOR_USER Database user that uses to connect to your database when executing API requests. Use authenticator as the username here (or then name you configured in .env file for DB_USER)
APP_DB_AUTHENTICATOR_PASSWORD Authenticator user password
APP_JWT_SECRET The JWT secret used by (and some functions in your database) to sign and verify JWT tokens.
Make sure the secret is at least 32 characters long!

git push to deploy

Whenever we are ready to deploy new changes, we just tag our revision and push the tag.

First make sure all your local changes are committed and pushed.

git status

The output should be similar to

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Now let's tag our current version

git tag v1.0

And push this tag

git push --tags

The new git tag will trigger the test and deploy jobs that will run all the database migrations and create (and later update) the configuration for your application.