Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Provision a Free PostgreSQL Server on Heroku

For more information on concepts covered in this lesson, you can check out:

Here are the command-line snippets used in this lesson:

$ heroku addons
$ psql `heroku config:get DATABASE_URL`
$ heroku pg:psql
<app-name>::DATABASE-> \l
<app-name>::DATABASE-> \d
<app-name>::DATABASE-> \q
$ heroku pg
$ heroku run python manage.py migrate
$ vim Procfile
$ git commit -am "Automate remote migrations"
$ git push heroku

Configuration File
web: gunicorn portfolio.wsgi
release: python manage.py migrate

00:00 In this lesson, you’ll connect your Django project to a standalone relational database server. Thankfully, Heroku automatically provisions a managed database service in the cloud at no charge through an add-on.

00:13 It takes the burden of installing, configuring, securing, and maintaining a relational database off your shoulders. When you first deploy an app, Heroku spins up a PostgreSQL database, which is coincidentally one of the most popular choices for Django projects.

00:30 Nevertheless, Heroku has special support for this particular database management system, regardless of whether you use Python or not.

00:40 You may recall a DATABASE_URL environment variable in your app’s configuration, which Heroku defined for you. As you can see, it’s an address to an EC2 virtual machine on Amazon’s AWS infrastructure, which hosts a PostgreSQL database on the default port.

00:57 So, if you happen to have PostgreSQL installed locally, then you can use this public address to drop into the interactive terminal and start typing SQL queries against your remote database.

01:09 On the other hand, if you don’t have the PostgreSQL tools, then you can rely on the Heroku CLI, which provides a convenient pg:psql wrapper command that achieves the same effect.

01:21 That’s even quicker than manually copying and pasting an address buried somewhere in remote configuration. Interestingly, once you’re connected, you can list all the available databases owned by other Heroku apps that don’t belong to you. While you can’t open them, it shows that data between the individual apps shares the same infrastructure and may not be isolated enough for sensitive information storage.

01:47 Some countries have strict laws that require additional separation of medical records of patients, for example. Keep in mind, that’s one of the limitations of the free Heroku account, but there are more. When you type heroku pg, it will show your database’s status.

02:06 Among the displayed information, you’ll see that you have a pool of at most twenty connections, only one gigabyte of storage, and just 10,000 rows. Other than that, replication and rollbacks are unsupported.

02:22 That said, these constraints shouldn’t really be a big deal in a hobby project. Back to your provisioned database, when you list your tables, then you’ll find out there are none, even though you might have run the Django migrations before. That’s because you ran them locally against a file-based SQLite database.

02:44 Normally, you’d have to tell Django how to connect to the database provisioned by Heroku by installing the PostgreSQL driver and by updating your Django project settings accordingly. However, if you were following along, then there are no extra steps to take.

02:59 The django-heroku library comes with the right driver out of the box and picks up the database URL variable to configure your Django settings for you.

03:08 By the way, if you run into issues with django-heroku, which isn’t maintained anymore, then you can try the slightly newer django-on-heroku fork, which uses a binary driver for a PostgreSQL database.

03:23 To apply the migrations remotely against your PostgreSQL instance, you must start a temporary Heroku container and manually run the migration command in it.

03:34 This will populate the provisioned PostgreSQL instance by creating the default app’s tables. Unfortunately, it’s easy to forget about applying pending migrations when you make new deployments. Therefore, Heroku lets you automate this task by specifying a special process in the Procfile. Go ahead and edit the Procfile.

03:55 Add a release process, and type the migration command that will run after each deployment.

04:05 Now, commit your automated migrations and push the code to Heroku to trigger a build.

04:22 Once finished, you should see the familiar output in the terminal. In this case, there were no migrations applied because your database schema hasn’t changed.

04:32 You can try modifying your data model and make another deployment to see if there’s any difference as an exercise. When you push the code to Heroku or change your app’s configuration, it creates a new release, hence the release process in your Procfile.

04:47 You’re going to learn more about releases, what they are, and how to manage them in the next video.

Avatar image for Denilson Noa

Denilson Noa on Nov. 3, 2022

I cannot find the DATABASE_URL.

Avatar image for Bartosz Zaczyński

Bartosz Zaczyński RP Team on Nov. 4, 2022

@Denilson Noa How do you check your environment variables? I just created a test Heroku app with Django, and it provisioned a new PostgreSQL instance with the corresponding DATABASE_URL variable in my app’s config. Perhaps you haven’t pushed your code to Heroku, which didn’t trigger the initial deployment?

Avatar image for bgersten

bgersten on March 7, 2024

I have pushed my code to heroku many times during the course and don’t have a DATABASE_URL variable in my current config file. It only displays the fake SECRETE_KEY. Perhaps I have deleted the URL somewhere during the course. Otherwise, I am up to date. How do I insert a new PostgreSQL instance into my app at this point?

Second, I wanted to change the WEB_CONCURRENCY environment variable as you suggested in the previous lesson, but couldn’t find where to do it. Where is it located?

Avatar image for Bartosz Zaczyński

Bartosz Zaczyński RP Team on March 8, 2024

@bgersten The DATABASE_URL environment variable only gets defined when you provision a database as a Heroku add-on. Did Heroku provision one for you? You can check by issuing the heroku addons command in your terminal. Note that Heroku removed their free plan some time ago, which might explain the discrepancies you’re experiencing.

Heroku doesn’t create the WEB_CONCURRENCY environment variable for you. This variable is optional, letting you override the default number of workers in Gunicorn. You can set that variable using the Heroku CLI with heroku config:set WEB_CONCURRENCY=4, for example, or you can use Heroku’s web dashboard to do so.

Avatar image for bgersten

bgersten on March 8, 2024

@Bartosz Zaczyński, heroku addons command shows “No add-ons” in my app. It makes sense that the DB is no longer automatically provisioned if the Basic dynos tier is no longer free. I am surprised since the first lesson of this course states that Heroku is free in several places. I would suggest that a notice be placed in the first lesson text that Heroku is no longer free.

Avatar image for Bartosz Zaczyński

Bartosz Zaczyński RP Team on March 11, 2024

@bgersten That’s a fair point. I’ve added a side note with updated information regarding Heroku’s pricing changes to prevent any further confusion for new students. Thank you for bringing this to our attention!

By the way, you can try Dokku—a free and open-source alternative to Heroku with a similar interface and the underlying concepts.

Become a Member to join the conversation.