DEV Community

Cover image for Django Deployment - Postgres DBaaS
rburkhardt
rburkhardt

Posted on • Originally published at rburkhardt.com

Django Deployment - Postgres DBaaS

During my last attempt to get a Postgres server up and running, I realized again how time consuming it actually is. In addition to the installation of the Postgres server, the whole server has to be secured. This can take a lot of time. With a small vps with many users there is also the limited perfomrnace.

The alternative: DBaaS (Database-as-a-Service).

The advantages of a DBaaS are simple:

  • Time saving (server management and installation)
  • Security ( reduced risk and best practice)
  • Data-Security (automatic backups)
  • Scalability (fast and easy to scale down and up)

Providers I can recommend are:

The service from fly.io Postgres on Fly also looks very promising.

Preparations

Postgres

  • login: psql -U doadmin -h host -p port -d database
  • database creation: CREATE DATABASE djangodb;
  • switch to the new db: \c djangodb;

After that we can create the new user with a secure password:

CREATE USER djangouser WITH PASSWORD 'securepassword';
Enter fullscreen mode Exit fullscreen mode

For everything to work smoothly django recommends the following paramenter (see django-docs):

ALTER ROLE djangouser SET client_encoding TO 'utf8';

ALTER ROLE djangouser SET default_transaction_isolation TO 'read committed';

ALTER ROLE djangouser SET timezone TO 'UTC';
Enter fullscreen mode Exit fullscreen mode

Finally we can change the privileges for our new user:

GRANT ALL PRIVILEGES ON DATABASE djangodb TO djangouser;
Enter fullscreen mode Exit fullscreen mode

Django

Here i decided to use django-environ's env.db() for the DATABASE_URL.


import os
from pathlib import Path
import environ

BASE_DIR = Path(__file__).resolve().parent.parent

env = environ.Env()
env_file = os.path.join(BASE_DIR, ".env")
if os.path.isfile(env_file):
    env.read_env(env_file)

DATABASE_URL = env.str("DATABASE_URL", default=False)

if DATABASE_URL:
    DATABASES = {"default": env.db()}
else:
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": BASE_DIR / "db.sqlite3",
        }
    }

Enter fullscreen mode Exit fullscreen mode

Note about DigitalOcean's App Platform:

If we use DigitalOcean's App Platform, we can skip the dynamic variable ${dbname.DATABASE_URL} as DATABASE_URL. This has always led to an empty database for me with a redeploy. Even if I created a database via DO's GUI before, and changed the variable accordingly.

To ensure that our data is also available after a redeploy in the future, we can use the Postgres-String as variable (with encryption on).

Conclusion

(in connection with DO's Postgres DBaaS)

I am very happy with the performance so far. If I need connection pooling (via PgBouncer) later, I can add it quickly and easily via DO's GUI. The price is a bit expensive for a single and smaller project, but quickly pays off when another project is added. With DigitalOcean the fun starts at 15€ and 3 databases (1GB Memory, 1 vCPU, 15GB Disk).


Thanks for reading.

Originally published at rburkhardt.com
Feel free to subscribe to my RSS and connect on Twitter or Github

Top comments (0)