The Essential Django Deployment Guide
Everything you need to know to get your Django app into production.

November 28, 2022

Congratulations, you finished your first web app! Your models are perfect. You've tested all your views. You even managed to figure out how to make that fancy thing work in JavaScript. It's beautiful!

There's only one little problem...

...your beautiful new app only runs on your laptop.

On my laptop meme

If your app only runs on your laptop and no one else ever sees it, does it even exist?

Now you want to make it available to the world only... you have no idea what that entails. And so you google "Django deployment" but you keep seeing different answers. Something about Apache or Nginx? No, that's from years ago. Heroku? Were people abandoning them recently? Docker? Kubernetes? Serverless??? You just want the damn thing on the internet but it all feels so... complicated.

If this sounds like you, then you're in the right place. The world of Django deployment is huge and complicated, but that doesn't mean it has to be for you. In this guide we'll cover the big picture decisions you'll make when deploying your Django application—from choosing a hosting strategy to the nitty-gritty details of where to store your passwords. Hopefully after reading it you'll walk away with a better understanding of how to make these choices, and clear path forwards for your new little corner of the Internet.

Where we're headed

We'll start by reviewing the basic components of a production Django application so it's clear what we're even talking about. Then we'll choose a deployment architecture—and specifically dive into the details between using a VPS or a PaaS. With that choice out of the way we can move on to choosing a hosting company.

Finally, having made our high-level decisions, we can get into the details—including what technologies to use (and the little details that come up when using them), and how to prepare your app for production.

Hopefully by the end of it you'll have a good sense not only of how to set up a production Django application, but also why to choose certain ways of doing it over others, and the best fit for your specific project.

Here's the complete outline:

Let's get into it!

Don't have a Django app to deploy yet?

Consider SaaS Pegasus for your next project. It's a Django-based starter project with account management, billing, teams, a modern front end, and near-instant deployment built in.

The components of a production Django application

Before we get into deployment specifics we'll need a shared foundation of knowledge and vocabulary. So what is a production Django application anyways?

Here is the absolute simplest version of this:

Simple Architecture

The bare minimum architecture of a production Django site.

On top we have the Internet, which is our gateway to our users. They access our site via a web server, which in turn calls our Django code. If any data needs to be looked up or stored, our Django code will do that in a database. Additionally we may want to serve some static files—images, CSS, JavaScript and so on—which we'll just stick off to the side for now.

This is the minimal Django application.1 In practice, most apps end up looking more complicated, but in this guide we're going to focus on this starting point, because even getting these four little pieces running properly in production involves a lot of decision-making and complexity!2

Choosing your deployment architecture

The universe of ways to deploy Django is immense, ranging from "running thousands of physical servers in a data center" to "uploaded this config file somewhere and magic happened". Because this universe of options is so big, the first thing we want to do is narrow it down, by zeroing in on a specific type of deployment architecture. That's the goal of this section.

Before we get started, some assumptions. First, this guide is largely for non-enterprise projects: startups, small teams, agencies, solo-developers, and so on. If you work for Amazon, your priorities will be quite different. It also assumes you're building a relatively standard web application—with data models, views, a front end, etc. If you're building a Stable Diffusion avatar app that needs hundreds of GPUs per minute, you should turn elsewhere for advice.

Given those assumptions, the first—possibly controversial—thing we can do is eliminate broad swaths of deployment architectures. You probably don't want to use Kubernetes. You also probably don't want to use serverless. They're just too complicated, expensive, and won't add any real value for your app.

Kubernetes

Kubernetes actually is useful for some projects, just probably not yours. Source: Dilbert/Reddit.

Are there exceptions to those recommendations? Absolutely. If you spent the last five years maintaining an app on top of Kubernetes and love it, by all means go ahead and use it! But these are exceptions, and here we're just aiming to help the average person get their app online.

With those choices out of the way we'll focus on the biggest decision: VPS or PaaS? Let's first do a refresher on what those mean.

VPS-based deployments

VPS stands for virtual private server. The simplest way to think about it is a full-blown computer in the cloud.3 VPS's have an operating system (in the Django world, usually Linux), and a certain amount of processing power (CPUs), memory (RAM), and disks. You manage a VPS similar to your laptop—setting up user accounts, installing your own software, and so on. Common examples of VPS hosting include Digital Ocean droplets, Linodes, and the AWS lightsail and EC2 products.

Deploying on a VPS allows for a fairly monolithic architecture. One way we can deploy our above components on a VPS is just to throw everything onto it. Our architecture diagram would look something like this:

Simple Architecture VPS

On a VPS you can run every piece of your application directly on the server.

There's plenty of room for modification to this diagram, but this is how most VPS-based deployments start. In the VPS world we install and run all the software we need—from the web server to the database—directly on our server. From that perspective, a VPS-based deployment is pretty simple!

But—while the picture looks simple, it's masking quite a lot of complexity. The first Google result for "Django Ubuntu production" is a 5,000 word tutorial on the subject. And if it's your first time deploying a production Django app you can expect a lot of troubleshooting and a healthy dose of self-doubt as you wonder if you managed to do everything in the right, secure, sustainable way.

How things can go wrong on a VPS.

One example of how things can quickly go wrong when deploying to a VPS.

And that's just setup. Another problem with running your app on a VPS is maintenance. When something goes wrong, you're on the hook for figuring it out. And similarly, if one of your dependencies requires an urgent security patch, you're the one responsible for knowing and dealing with that.

VPS Maintenance problems.

Maintenance can also be a big time-sink with VPS-based deployments.

Finally, if you ever need to set up your app a second time—say, because you're setting up a staging environment or changing hosting companies—you'll have to re-do all those setup steps again. There are tools that help with this, but they are themselves complicated, one more thing to learn, and hard to get right.

In short: VPS's are a lot of work!

Thankfully, PaaS-based deployments solve many of these problems for you.

PaaS-based deployments

PaaS stands for platform-as-a-service. When you use a PaaS, the server layer is hidden from you. Instead you use an API provided by the PaaS—usually one or more config files—and the PaaS handles the process of turning it into a running app—usually using Docker/containers under the hood.

On a PaaS you still choose processing power, memory and so on, but you typically can't manage user accounts or install your own software. Everything happens in the config file. Common PaaS offerings include Heroku, Render, Fly.io, and Digital Ocean App Platform.

Note: while the above definition of PaaS is common when talking about Django deployment, PaaS is a broader term that can also apply to other things. E.g. all of AWS is sometimes referred to as a PaaS. In this guide we'll stick to the above definition.

In the PaaS world your application is reduced to a container running some code. This is great because you only have to get that one little thing right and all the other pieces are taken care of for you—typically as managed services provided by the PaaS or some other third party.

A PaaS deployment looks something like this:

Simple PaaS Architecture

A typical architecture for running Django on a PaaS. We'll discuss a modification to the static files set up in the next section.

In this world you're only responsible for what runs in the blue boxes—which is the code you wrote. The grey boxes are fully run by the PaaS. It's more moving pieces than a VPS, but the part that you personally have to deal with is greatly reduced!

PaaS's solve many of the problems we encounter when setting up on a VPS. That long and messy installation process? Now just a few lines of configuration and you're good to go. It's possible for a novice to get an app up and running on Heroku or Render in under an hour. On a VPS that setup could take the same person days.

And it's not just set up. PaaS's will save you time in maintenance as well. Those database security patches will (mostly) be handled for you. And updating your production app can be as easy as "git push".

Perhaps even more importantly, using a PaaS also enforces a certain set of best-practices, making it harder for you to make glaring mistakes that are common when going to production. A PaaS will usually provide off-the-shelf data backup options. They'll also usually guide you in the right direction on security best-practices, keeping secrets secret, and so forth. You can definitely still make mistakes with a PaaS but it's a bit harder than with a VPS.

This all sounds pretty great. So what are the downsides of using a PaaS?

The most commonly-cited one is cost. Because these companies are handling a lot of the devops burden for you, they can charge a premium on a per-CPU or per-GB-of-RAM basis. This doesn't matter too much when your app is simple and your performance needs are low, but as you scale out the number of resources and services you need, the costs can quickly add up.

The other major downside of using a PaaS is the loss of flexibility and functionality that comes with having to work in a fully managed/containerized environment. Things that are trivial on a VPS but harder (or impossible!) on a PaaS include: running multiple processes on one machine, saving data to the file system, and running a cron-like scheduler. There are PaaS-friendly replacements for these things, but they often require learning a new tool and yet another external dependency. For those who are used to using VPS's, working with these constraints can be a very frustrating experience.

Choosing between a VPS and PaaS

The table below summarizes what we've covered so far:

VPS PaaS
How it works Install all the pieces of your app on your own computer(s) in the cloud. Run your app in a container(s) and rely on managed services for all dependencies (e.g. databases).
Common Examples Digital Ocean droplets, Linodes, AWS lightsail and EC2. Heroku, Render, Fly.io, Digital Ocean App Platform.
Set Up Slower and more complicated. Faster and easier.
Maintenance More handled by you, requires more knowledge. More handled by the PaaS, requires less knowledge.
Cost Generally cheaper, especially at scale. Competitive at low end. Can get very expensive at scale.
Flexibility Very flexible. Can do whatever you want. Less flexible. Constrained by the capabilities provided by the PaaS.
Working with files Easy. Complicated, requires another service.
Backups and Security Mostly have to handle on your own. Easier to mess up. More handled for you and easier to do properly.
Scalability Usually easier to scale up, e.g. adding more resources to your server. Maxes out at machine size, though this usually gets you very far. Usually easier to scale out, e.g. add multiple machines to process web requests.
Overall Powerful, flexible, and most affordable if you know what you're doing. But lots more work. Much easier to set up and maintain, harder to mess up, at the expense of some flexibility and cost at scale. A great option for most projects.

So which should you use? There's not a single right answer for everyone as both options have some pros and cons, but I would default to a PaaS unless I had a good reason not to. If it's your first production deployment I would be very cautious about using a VPS.

Here's a slightly more nuanced decision tree:

Choosing between a VPS and a PaaS

Most people reading this will likely go straight down the right side of this diagram and should use a PaaS—at least until they encounter some reason not to.

That said, I would feel a bit hypocritical throwing VPS's out the window, since I personally use them sometimes. Having your own servers in the cloud is fun and makes some things easier. And so for experienced solo-developers or teams with good devops skills, VPS can still be a great choice. Just recognize what you're signing up for!

Made your choice? Great! Now it's time to pick a hosting company.

Choosing a hosting company

Choosing a hosting company can feel a bit like choosing a spouse. There's tons of options out there and it feels like a big commitment. Definitely something you don't want to mess up!

The good news is unlike potential mates, there is far less variation among hosting providers than people. Most popular hosting companies will have similar feature sets and will serve the needs of your new app just fine. If you take away one thing from this section make it this: There is ~no wrong choice.

The other good news is that usually it is much easier to change your hosting company than to get out of a marriage.4 Yes, it might take some downtime and some work, but this particular partnership doesn't have to be for life. The recent exodus of people from Heroku is evidence that it can be done with a bit of work.

Marriage Decision

Thankfully the stakes for choosing a hosting company are lower than other life decisions. Source: Wait But Why.

I say all this because I've seen people agonize about choosing a hosting company—stricken by analysis paralysis—when they should be focused on just getting their app up and running somewhere. Once you realize the stakes are lower you can make any choice, which is far better than no choice. If you're not sure, give yourself a couple hours to play with a few different options and pick one you like. Or if you want more help deciding, try the recommendations below.

Note: Will Vincent has an excellent list of Django-friendly hosting options. The recommendations below are my own opinionated suggestions based on personal experience and feedback from other developers I trust. I have not tried every option, and most will probably work out fine.

Choosing a Django PaaS Provider

Here's the algorithm I would recommend for people choosing a PaaS in 2022:

Choosing a PaaS Host

An opinionated algorithm for choosing a PaaS company to host your Django app.

The most important part here is that if you're already happy using something, just stick with it! This goes back to the "they're all fine" point above.

If this is your first time setting up a production app, or are interested in switching off your current host, I would try one of Heroku, Render, or Fly.io.

Heroku is the best choice for product maturity and developer experience. Set up will be smooth, it will be well-supported, and there will be lots of resources out there to help with set up and troubleshooting. The major downside of Heroku is that—as of this month—they have no free tier. This can be a deal-breaker for hobby projects.

If you're cost-sensitive, Render and Fly.io are newer options that still have generous free tiers. They are both newer, a bit less well-documented and battle-tested than Heroku, but work great with Django. The main difference between them is that Render is similar to Heroku in that you configure it specifically for a Python project,5 whereas Fly.io is more Docker-file based.

To Docker or not to Docker...

Docker is a tool that lets you run things in containers—which you can think of as limited, less-powerful computers that usually do a single thing. Behind the scenes most PaaS platforms use Docker, and most also support using it explicitly—by providing a "Dockerfile" which is what Docker uses to set up and run the container.

The main benefit of using a Dockerfile-based deployment is that it provides incredible consistency and portability across environments. The same Dockerfile can run a container anywhere---in dev, staging, or production, and on any number of platforms. With a Dockerfile you also have more fine-grained control over exactly what gets installed/run in the container.

The biggest downside of using a Dockerfile-based strategy is that creating the right Dockerfile for your app is usually much more work than using the PaaS-provided config file which takes care of the details for you. It's one more thing to learn that will slow you down when you're just trying to get your app running.

TLDR: If you already know/use Docker—stick with it. If you don't, it's probably easiest to start with a non-Docker-based PaaS option.

Choosing a Django VPS Provider

In the VPS world things are simpler, and the decision is even lower stakes. VPS's are even more of a commodity than PaaS's—a server is a server no matter where it runs. The big factors in the VPS hosting decision are 1) complexity of set up, 2) support, and 3) cost.

Once again, here's a suggested algorithm:

Choosing a VPS Host

An opinionated algorithm for choosing a VPS company to host your Django app.

Similar to choosing a PaaS host—one of the biggest differentiators will be your own familiarity and speed with the platform. If you already have one you like, use it!

If this is your first project (and if so, you better have a good reason for choosing VPS) you can think of there being two high-level tiers of companies:

  1. Big, enterprisey cloud platforms that have tons of different options and services. E.g. Amazon Web Services (AWS), Google Cloud Platform (GCP), and Microsoft Azure.
  2. More user-friendly "just give me a server" options, like Linode and Digital Ocean.

If you're not sure which you want, this guide recommends going with a simple one like Linode or Digital Ocean. Platforms like AWS can be extremely confusing and complicated to use when you're first getting started. Linode is what I personally use, and I have always been very impressed with their support team. I've also had good experiences with Digital Ocean.

AWS

How it can feel getting up and running with AWS and other "enterprisey" cloud platforms. Source: Reddit.

That said, if you do need something more enterprisey, for example, AWS-specific services,6 regulatory compliance, and so on, then use one of the enterprises. AWS is recommended among the big players because it's the most popular, and therefore will have the biggest documentation and support ecosystem.

At the end of the day most of these companies will offer very similar services at competitive prices. At the risk of sounding like a broken record, pick one and move on! We've got an app to ship.

But what about ___________?

I've managed deployments on many different platforms for my Django boilerplate and other projects over the last decade. These suggestions are based on that first-hand experience—but there's many options out there, each with their own take on the deployment problem. If you think Heroku, Render, and Fly are garbage, go nuts with your cocktail of PythonAnywhere/Dokku/GCP. Use the one you like.

One last time for the people in the back—they're all fine.

Figuring out your supporting infrastructure

Alright, we've chosen our deployment architecture, we've chosen a hosting company, and we're finally ready to get up and running.

In this section we'll go back through our architecture diagrams from above and fill in some concrete details about what to put in those boxes.

Here is this guide's recommended choice of infrastructure when deploying on a PaaS.

Detailed PaaS architecture

Choosing infrastructure on a PaaS is relatively straightforward since the PaaS either provides most of these tools for you, or provides a menu of options for you to pick from. Below is a quick run down of the details.

Web server

This is the easiest one. On a PaaS your web server is automatically handled for you. The PaaS is responsible for getting your traffic to your application container, and—as long as you don't have any complicated routing requirements—you will basically never need to think about how it works. PaaS's will also typically handle SSL certificates for you—again without you having to do anything apart from point your DNS somewhere. This is a huge win for PaaS!

Django

Django will be running in our app container. But how do we actually do that? Do we just call ./manage.py runserver and call it a day?

Not quite, but it's not that far off! Instead of calling runserver we'll instead use gunicorn to run our Django app as a more-performant WSGI server. We can install it via pip and run it with a command that looks something like this, as described in the Django docs.

gunicorn my_project.wsgi

As with all things, there are other ways to do this, but gunicorn is the simplest and most common!7

Database

In addition to handling web traffic, most PaaS's also offer a managed database. The PaaS handles all the setup and configuration and you just pick which DB flavor you want and how big it should be. The PaaS will also typically provide backups, resizing, and other goodies. Another big win for PaaS!

Still—Django officially supports five different databases. So which should you choose?

Like everything else in the guide, if you already have a favorite, use that one. Otherwise, use Postgres. It's by far the most popular DB to use with Django, will have lots of support, and won't let you down.

Django DB poll

When it comes to choosing a database, Postgres is easily the elephant in the room (sorry). Source: 2021 Django Developer Survey

Static Files

Where to host your static files—images, JavaScript, and so on—can be a topic of much confusion. That's because there are several ways to deal with static files—some of which use the filesystem, and some of which use external storage services like S3, CDNs, and so on. Each of these options has its own set of (mostly-minor) pros and cons.

The main options are:

  1. Serve them with your web server directly from the file system. This used to be the most common option, though is difficult-to-impossible to do on a PaaS.
  2. Serve them from the Django process itself. This is often seen as a "bad" option because of the performance penalty you pay, but the WhiteNoise library dramatically mitigates that.
  3. Serve them from an external storage service. The most common option here is Amazon S3, or a compatible object storage service.
  4. One of the above, but layering in a content delivery network (CDN). This results in a performance benefit on top of the above options—especially if your users are far from your servers.

Of these, we recommend option 2 to start, which has the simplest set up and good-enough performance. WhiteNoise will prepare your files when you call collectstatic and—by default—serve them efficiently, directly from your Django app. Set up is just a few lines of configuration—as described in their setup guide—and there are no extra moving pieces.

For an extra boost of performance you can set WhiteNoise up with a CDN as described in Step 4 of their guide. This will certainly be performant enough for any project.

And...that's basically it in terms of architecture decisions on a PaaS!

Considerations if deploying on a VPS

I had originally hoped to include VPS-specific guidance in this section, but decided to defer that to a future writeup. Still, here's a quick picture of what I normally do:

Detailed VPS architecture

This picture masks a lot of nuance and complexity. Some quick notes

  • Nginx is chosen as the most popular Django web server, and like Django and Postgres, it's battle-tested, popular, and has a great support ecosystem. That said, there are other good options, including Caddy, HAProxy, and Traefik.
  • You'll also need to set up SSL, probably via a Let's Encrypt certificate.
  • You may choose to serve static files directly from your web server (option 1 above) instead of through WhiteNoise.
  • You'll probably still use gunciorn for Django, but you'll also need some kind of process manager like systemd or supervisord. And you'll need to set up a Python virtual environment, etc.
  • Alternatively, you can do almost all of this with Docker instead.
  • Etc.

I told you VPS's were complicated!

The other details that matter

Alright, we've chosen our architecture, hosting company, and supporting infrastructure. What's left?

Unfortunately, we're not quite done. In this section we'll quickly touch on many of the common things that come up with deployment and provide some suggestions on handling them. If you're using a PaaS and get through all of these you should be in good shape!

Build and release commands

(This section is largely PaaS-specific, though the high-level principles also apply to VPS's.)

There are often sets of commands that you want to run with every production release. At a minimum you probably want to run ./manage.py collectstatic to collect your static files, and ./manage.py migrate to apply any new database migrations. But... where do you do that?

The answer is nuanced, but the short version is either in your app's build or release phase.

What are these phases? The build phase is when your application is being built. At the beginning of the build phase you have a config file, and at the end of it you have a container capable of running your application. Everything that happens in between is the build phase. If you use Docker then you can think of the build phase as everything that happens inside the Dockerfie.

In contrast, the release phase happens when your app is...well... released. It takes the fully-built container and gives you an opportunity to run some stuff exactly once, when the app has just been updated.

Application phases

The theoretical build and release phases. On a PaaS, your application container is ready after build and before release. These phases are sometimes combined.

Some PaaS offerings (e.g. Heroku) have both phases, but some (e.g. Render) combine them into a single step. On a VPS you'd define the phases yourself. Either way, here's where you should try to run common commands:

Front end builds and collectstatic should run in the build phase. Your collected static files (including any compilation steps) are part of your app's build and so should be run at build time—especially if you're using WhiteNoise to serve static files. In fact, on some platforms running these commands at release time will not work which can lead to unexpected problems.

Database migrations should be run in the release phase. This helps to avoid the possibility of migration being run multiple times, run for builds that later fail, and so on. Also, in the Docker world it's generally bad practice for building the container to have database-level side effects.8

On a PaaS, a common pattern for managing build and release commands is to create a build.sh or release.sh file with everything you need to run in that phase.

For example, build.sh:

#!/usr/bin/env bash
set -o errexit  # exit on error

echo "Installing python dependencies"
pip install -U pip
pip install -r requirements.txt

echo "Building JS & CSS"
npm install
npm run build

echo "Collecting staticfiles"
python manage.py collectstatic --noinput

And release.sh:

#!/usr/bin/env bash
set -o errexit  # exit on error

echo "Running database migrations"
python manage.py migrate --noinput

On a platform like Render with only one phase, these would be combined to a single file.

Managing settings and secrets

Production applications need different settings than development. In dev you'll probably have DEBUG set to True but you'll want to disable that in production. On top of that, your production settings will also include secrets—your SECRET_KEY, database passwords, 3rd-party API keys, and so on. We definitely don't want these in source control. So how do we deal with that?

It used to be common practice to keep a git ignored settings file directly on your production server—named something like localsettings.py or settings_production.py— and dump all the configuration changes and secrets there.

For example, yourapp/settings_production.py:

from .settings import *  # import all base settings

DEBUG = False  # disable debug mode

# other settings overrides and secrets
SECRET_KEY = 'i82oucq83d1vzqenw4yv7ef03fey8kb4gww4mt8qntwh35d7sz'
MY_BANK_PASSWORD = 'hunter2'
# and so on...
A typical production settings pattern. You'd then run your app by passing in --settings=yourapp.settings_production or setting the DJANGO_SETTINGS_MODULE environment variable.

With the advent of PaaS's and the twelve-factor app, this pattern has largely gone out of favor. It's now more common to use environment variables—which are managed by the PaaS—for custom settings. This has an added benefit of letting you take all the secrets out of your production settings file, which allows you to check it into source control.

In this world, your settings_production.py file looks more like this:

from .settings import *   # import all base settings
import environ

env = environ.Env()

DEBUG = False   # disable debug mode

# other settings overrides and secrets pulled from the environment
SECRET_KEY = env('SECRET_KEY', default='insecure')
MY_BANK_PASSWORD = env('MY_BANK_PASSWORD', default='')
# and so on...
A production settings file using environment variables. This example uses the excellent django-environ library, though you can achieve the same thing with os.env or other alternatives.

This file is totally safe to check into source control. Yay!

You can even take this one step further and put everything directly in your settings.py file. Then you don't even need multiple settings files. This can be a bit tedious to set up—especially if you have lots of settings that are different in dev and prod—but it does simplify things. If you do it this way you'd also likely use a .env file to manage your dev settings:

import environ

env = environ.Env()
env.read_env(os.path.join(BASE_DIR,  ".env"))  # also read from a .env file for dev environments

# DEBUG now controlled by an environment variable which allows using the same file in dev and prod
DEBUG = env.bool('DEBUG', default=True)

# other settings overrides and secrets pulled from the environment
SECRET_KEY = env('SECRET_KEY', default='insecure')
MY_BANK_PASSWORD = env('MY_BANK_PASSWORD', default='')
# and so on...
Same example, but with a single `settings.py` file, and reading from a .env file for convenience.

Security

Security is a long and complex topic that's largely out of scope for this guide. Also, the good news is that if you're using a PaaS there is much less to worry about—no messy user permissions, firewalls, database configs or any of that.

Still, Django itself has many security-based features and settings that you should review before finalizing your production deployment. Django provides a deployment checklist that helps ensure your site has some of the most important settings properly configured for production environments. You should run it by calling manage.py check --deploy on your production server and addressing/understanding the issues that are flagged.

Monitoring

There are two pieces of monitoring that this guide recommends setting up on every project.

The first is an error monitoring service, which will alert you every time your application encounters an error. They help you find out in real-time when your users encounter problems, and give you the information needed to fix them. I use and recommend Sentry, which integrates in your code in minutes and has a great free tier for individuals. I have no affiliation with them—just a big fan.

Sentry Drake

Sentry does a great job integrating with Django and letting you stay on top of your errors.

The second one is an uptime monitoring service, which will ping your app every minute or two and tell you if something goes wrong. It prevents those embarrassing "my site was down for three days before I realized it" type of errors. There are lots of services that provide this. I personally use Status Cake which has done everything I've ever needed on the free tier, though I'm sure there are lots of good options.

Backups

The last non-optional9 piece of a production deployment is setting up data backups. At a minimum you want to make sure you have a backup plan for your database, and ideally also any other user-generated content (e.g. media files).

Thankfully, a PaaS will usually take at least a daily snapshot of your database for you, which is sufficient to safeguard against catastrophic failures. Just double check and make sure that it is true and (if necessary) turned on! If your app needs a better backup strategy than whatever your PaaS offers, you'll need to figure out how to set that up.

Considerations for a VPS

Once again, covering all the additional details for a VPS-based deployment was just too much to bite off in this version of the guide. Most of this stuff is similar on a VPS, but with more pieces to figure out. For example:

  • You can manage secrets the same way, but also need to figure out where to stick your environment variables.
  • You'll still want to go through the security checklist, but also have to worry about locking down your server accounts, network, and so forth.

A complete guide for VPS-based deployments might include these other topics and steps—perhaps a subject to tackle in a future guide:

  • How to install everything. By hand vs using automation like Ansible.
  • How to set up Python, using virtual environments and such.
  • How to run your processes, e.g. systemd or supervisor.
  • Docker-based deployments on a VPS—what they look like and the pros and cons of using them.
  • Choosing and configuring your web server
  • How to push updates, run release commands, etc.
  • Everything else already covered above for PaaS's

There are just way more options, decisions and things to sort out. One more time: VPS's are a lot of work!

Wrapping up

If you made it this far, congrats. There's a good chance your app is ready for the world and you can feel confident in the decisions you made along the way.

Now's the fun (and for many, the hardest) part—go share it with the world! Send it to your mom. Write a Tweetstorm—or a Tootstorm? Post it on Reddit. Try out LinkedIn again for the first time since you changed jobs... Don't be shy!

Of course, you're not done with your project by any stretch of the imagination—and in fact, in many ways this is just the beginning. Still, take a moment to congratulate yourself on a job well done, and don't forget to enjoy the ride. :)

And by the way, if you aren't yet ready to deploy your app, you may want to check out my product SaaS Pegasus. It's a Django codebase that's helped hundreds of Django developers launch their apps faster than they dreamed possible. It'll make deployment—and many other parts of your app—a breeze.

...to be continued?

So this guide only managed to cover a fraction of what I intended to when I started. If there's interest, I'll turn it into a series like I did with "Modern JavaScript for Django".

Some things I could cover next include...

1. What an expanded architecture might look like. For example, how you might set up something like this, which has media files, background workers, and a cache thrown in the mix.

Expanded Archiecture

Our minimal Django architecture with a few more common parts added.

2. A deeper dive covering deployment to a VPS and many of the details we glossed over. This would cover a lot of the steps above, but at a level of depth that could be practically applied to a VPS.

3. A tutorial-like guide to setting up on one or more PaaS platforms using the above recommendations. I avoided touching on many PaaS-level specifics in this guide because I wanted to keep it high-level, and because a lot of that content is already available for specific PaaS's. But maybe it's still useful?

4. Move on to a different topic. Alternatively, perhaps this is enough content related to deployment and I should get back to another aspect of Django—probably something more coding-focused.

Anyway, if you feel like it, you can vote on the outcome below to help inform my decision!

What should the next article be about?

Put this in if you want me to email you when it's ready

And, as always if you liked this guide, hated it, have suggestions, or want to get in touch about anything at all, shoot me an email at [email protected] or tweet me at @czue.

See you next time!

Other Resources

The following resources came up in the process of writing this guide.

Choosing a hosting company

Other tools and options

  • django-simple-deploy is a useful project to make deployment to a handful of PaaS companies very easy. I haven't used it but it comes highly recommended!
  • Appliku offers a PaaS-like deployment experience on top of your own VPS. It can greatly streamline the VPS setup process. I also haven't used it, but it's been recommended to me multiple times.
  • CapRover and Dokku are open-source PaaS offerings that use Docker to help you quickly set up a Docker-based deployment on a VPS. Again—no firsthand experience, but they come recommended.

Notes


  1. Ok, technically the Database is optional too but if you're not using a Database you'd be more likely to choose a lighter-weight Python framework like Flask. 

  2. Also, I wanted this guide to be 10 pages instead of 100. 

  3. The virtual in VPS means it's usually not actually a computer, but rather a virtual machine running on a larger computer, but this detail is largely irrelevant to you. You can also rent a dedicated actual, physical server, which can provide better value and more consistent performance than a VPS, but at the cost of hardware failure risk, slower set up time, and a more difficult migration/upgrade process. This is relatively uncommon to do these days. 

  4. Not that I would ever think about that...love you, honey! 

  5. Render does have Docker support as well, but it's less mature and missing key features like a release stage, which make it not quite ready for Django apps. 

  6. AWS offers proprietary services for everything from basic infrastructure (e.g. SQS) to machine learning models. 

  7. One consideration here is that if you're already using the asynchronous views in Django with asgi then you may need a different option. The Django docs suggest Daphne, Hypercorn, and Uvicorn

  8. On top of this, on some platforms the build phase won't even have access to the secrets from the app's environment or connectivity to the database, making it impossible to run migrations there. 

  9. Unless you too like to live dangerously. 

  10. Don't worry too much about the details of this for now. Or if you want a longer writeup of it, see this guide on a Django Celery integration

Subscribe for Updates

Sign up to get notified when I publish new articles about building SaaS applications with Django.

I don't spam and you can unsubscribe anytime.