Deploy Django on Northflank

Deploy Django on Northflank: build from Git with a Dockerfile or buildpack, add PostgreSQL and Redis addons, share configuration with secret groups, run migrations as a job in a release flow, add Celery workers, and expose the app with a custom domain.

Problem statement

You want a platform that handles builds, databases, workers, scheduled jobs, and preview environments for a Django project, with an option to run in your own cloud account later. Northflank combines container services, managed addons such as PostgreSQL and Redis, jobs, and pipelines. A Django project maps onto it cleanly, but you need to decide how configuration is shared between services, how migrations run before new code receives traffic, and how workers are deployed.

Django on NorthflankBuild servicefrom GitWeb serviceGunicorn, portAddonsPostgres, RedisRelease flowmigrate job, deployServices, addons, and jobs together cover web, workers, data, and migrations.
  1. Create a project, connect the Git repository, and add a combined service (build and deploy) using your Dockerfile.
  2. Add PostgreSQL and Redis addons and link their connection details into a secret group.
  3. Put Django settings (SECRET_KEY, ALLOWED_HOSTS, DJANGO_SETTINGS_MODULE) in the same secret group and attach it to every service and job.
  4. Create a manual job that runs python manage.py migrate --noinput with the same image, and run it in a release flow before deploying web.
  5. Add a deployment service for Celery with the same image and a worker command, and expose only the web service publicly.

Step-by-step solution

1. Build the image

A combined service builds from a branch and deploys the result. With a Dockerfile, the image is the same for web, worker, and jobs:

FROM python:3.12-slim
ENV PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN DJANGO_SETTINGS_MODULE=config.settings.build python manage.py collectstatic --noinput
CMD ["gunicorn", "config.wsgi", "--bind", "0.0.0.0:8000", "--workers", "3"]

A minimal config.settings.build module that does not require database or secret variables lets collectstatic run during the build. In the service, expose port 8000 as HTTP and mark it public.

Create a PostgreSQL addon and a Redis addon in the same region. Northflank exposes their connection details (host, port, credentials, connection URI) as variables you can link into a secret group, so services receive, for example, DATABASE_URL and REDIS_URL without copying passwords by hand.

what each resource runsRunsPublic?Combined servicebuild + web (Gunicorn)yesDeployment serviceCelery worker, beatnoJobmigrate, cron commandsnoAddonsPostgreSQL, RedisprivateSecret groupshared env variablesn/aOne image, several runtimes, one shared configurationdjango-deployment.com
Attaching one secret group to all of them keeps settings in sync.

3. Share configuration with a secret group

Create a secret group with:

DJANGO_SETTINGS_MODULE=config.settings.production
SECRET_KEY=<generated>
ALLOWED_HOSTS=.code.run,shop.example.com
CSRF_TRUSTED_ORIGINS=https://shop.example.com
DATABASE_URL=<linked from Postgres addon>
REDIS_URL=<linked from Redis addon>

Attach it to the project or to selected services and jobs. Changing a value then updates every service that uses it on the next restart. Northflank's default public domains end in code.run; include them in ALLOWED_HOSTS until you add your own domain.

4. Run migrations in a release flow

Create a manual job that uses the image from the build service with the command:

python manage.py migrate --noinput

A release flow (pipeline) can then run: build, run migrate job, wait for success, deploy the web and worker services. If the migration fails, the flow stops and the old version keeps serving.

5. Add workers and scheduled tasks

Create deployment services from the same build for:

  • celery -A config worker -l info --concurrency 4
  • celery -A config beat -l info (exactly one instance)

Or use Northflank cron jobs to run management commands on a schedule instead of beat. Keep worker services private.

pipeline order1Build from branchDockerfile, commit SHA2Run migrate jobsame image3Deploy web servicehealth check passes4Deploy workersCelery, beat5Promote or roll backprevious buildSchema changes land before any new code runsdjango-deployment.com
Backward-compatible migrations keep old workers running safely during the switch.

Explanation

Northflank separates building, running, and one-off execution into services and jobs, all of which can reference the same image and configuration. That fits Django's process model: one codebase, several commands. Addons provide the stateful pieces, and secret groups wire their credentials into the stateless pieces. Release flows add ordering, which is what makes migrations safe.

Edge cases / notes

  • Bring your own cloud. Northflank can deploy into your AWS, GCP, or Azure account; the Django setup stays the same, but networking and database choices may change.
  • Preview environments. Templates can create a full environment per pull request, including addons; seed them with anonymized data.
  • Media. Use object storage with django-storages; service disks are not shared across instances.

Next steps

FAQ

Do I need a Dockerfile on Northflank?

No, buildpacks are supported, but a Dockerfile gives predictable builds for web, workers, and jobs.

How do I run migrations on Northflank?

As a job using the same image, run before deploying the web service, ideally in a release flow.

Where do database credentials come from?

From the PostgreSQL addon, linked into a secret group that services and jobs share.

Can I run Celery beat?

Yes, as a separate service with one instance, or replace it with Northflank cron jobs.

Keep going