Oct 23, 20266 min read

How to Deploy a Django App to AWS with an AI Coding Agent

What Claude Code or Cursor has to change when you ask it to deploy an existing Django project to AWS with Postgres, done by hand on ECS and RDS, and with Encore added to the project as an infrastructure SDK.

A Django project that runs with manage.py runserver on a laptop is a long way from one that serves traffic on AWS.

When you ask an agent to deploy it, the agent has to pick a place to run the container, give it a Postgres database it can reach, move secrets out of settings.py, as the twelve-factor app recommends for config, and work through Django's deployment checklist, which covers DEBUG, SECRET_KEY, ALLOWED_HOSTS and HTTPS settings among others. Each of those is a place where a model can produce something that looks right and fails on the first request.

This guide compares the two routes an agent can take with an existing project, keeping the Django code itself the same in both.

Deploying Django to AWS at a glance

StepWith EncoreECS and RDS by hand
Django codeUnchanged apart from DATABASESUnchanged apart from settings read from the environment
Databasepostgres.Database declared in PythonRDS instance with its subnet and security groups
Local Postgresencore run starts Postgres locallyA Postgres the agent installs or runs itself
SecretsPer environment, outside the repoSecrets Manager entries injected into the task
ComputeProvisioned on deployDockerfile, ECR, ECS service and load balancer

ECS and RDS by hand

The common AWS layout for Django is a container on ECS with Fargate behind a load balancer, with Postgres on RDS. In settings the agent replaces hard-coded values with environment variables:

import os DEBUG = os.environ.get("DJANGO_DEBUG") == "1" SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] ALLOWED_HOSTS = os.environ["DJANGO_ALLOWED_HOSTS"].split(",") # Injected into the ECS task from Secrets Manager and the task definition. DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": os.environ["DB_NAME"], "USER": os.environ["DB_USER"], "PASSWORD": os.environ["DB_PASSWORD"], "HOST": os.environ["DB_HOST"], "PORT": os.environ.get("DB_PORT", "5432"), "CONN_MAX_AGE": 60, } }

Then it writes the infrastructure: an ECR repository and a Dockerfile, an ECS cluster and service, an Application Load Balancer, the RDS instance in private subnets, and task definitions that pull the password from Secrets Manager with an execution role allowed to read it. python manage.py migrate also needs somewhere to run, usually a one-off ECS task before the new version takes traffic. This setup gives full control and is well documented, and it is a lot of surface for an agent to get right without a real AWS account to test against.

Encore: Django with an infrastructure SDK

Encore

Encore combines an open source infrastructure SDK, which the Django project imports for its database and other resources, with a platform that provisions those resources in your own AWS account. Django keeps its ORM, admin, URL routing and migrations. The changes below come from the Django example in the Encore SDK repository.

The project adds encore-dev and psycopg to its dependencies:

[project] name = "django-hello-world" version = "0.1.0" requires-python = ">=3.14" dependencies = [ "django>=5.2,<6", "encore-dev", "psycopg[binary]>=3.2", ]

Note that the example sets requires-python = ">=3.14", so a project on an older Python needs an upgrade before it matches this setup.

An encore.service.json in the project root names the service and exposes its routes:

{ "name": "django_hello_world", "lang": "python", "api": [ { "type": "http", "prefix": "/", "name": "django_hello_world", "expose": true } ] }

The database and an object storage bucket are declared in a module of their own. Django still owns the schema, so no migrations directory is passed:

"""Encore discovers this declaration and provisions storage and PostgreSQL.""" from encore.storage import objects from encore.storage import postgres uploads = objects.Bucket("uploads") # Django manages the schema through its own migrations. db = postgres.Database("django")

settings.py builds DATABASES from the connection string the SDK provides, parsed with psycopg's conninfo helpers so escaping and options are preserved:

from psycopg.conninfo import conninfo_to_dict from storage.resources import db connection = conninfo_to_dict(db.connection_string) DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": connection.pop("dbname"), "USER": connection.pop("user", ""), "PASSWORD": connection.pop("password", ""), "HOST": connection.pop("host", ""), "PORT": connection.pop("port", ""), "OPTIONS": connection, } }

A small main.py adapts Encore's listen address to Django's development server, and installs Encore's tracing, metrics and log handler:

"""Adapt Encore's listen address to Django's development server.""" import logging import os from django.core.management import execute_from_command_line from encore.logs import ConsoleHandler from encore.metrics import meter_provider from encore.tracing import tracer_provider from opentelemetry import metrics, trace from opentelemetry.instrumentation.django import DjangoInstrumentor def main() -> None: os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") trace.set_tracer_provider(tracer_provider()) metrics.set_meter_provider(meter_provider()) DjangoInstrumentor().instrument() logging.basicConfig(level=logging.INFO, handlers=[ConsoleHandler()]) address = os.environ.get("ENCORE_LISTEN_ADDR", "127.0.0.1:8000") # Encore restarts the service on changes; a second reloader is unnecessary. execute_from_command_line(["manage.py", "runserver", address, "--noreload"]) if __name__ == "__main__": main()

encore run starts Postgres locally and runs the project against it. Management commands run through encore exec, so the SDK receives its runtime configuration:

encore exec -- uv run python manage.py migrate encore exec -- uv run python manage.py createsuperuser

The agent can then open the admin and call views before anything is deployed, which lets it catch a broken setting itself before it hands the change over.

On deploy, Encore provisions the database and compute in your AWS account.

Encore does not run Django migrations. Django owns the schema, so run migrate as a release step before the new version serves ORM endpoints. The runserver adapter in main.py is for local development, and this guide does not cover a production server setup.

Instance size, backups, networking and scaling are set per environment rather than in the Django code. The agent changes Python files, and cloud access sits with Encore's IAM role, not the agent.

Only admins can approve new infrastructure when a declaration adds a resource.

Good to know

The settings from Django's checklist still apply. DEBUG should come from the environment rather than the file, as in the hand-built route. SECRET_KEY can come from an Encore secret, since the Python SDK supports secrets:

from encore.secrets import Secret django_secret_key = Secret[str]("DjangoSecretKey") SECRET_KEY = django_secret_key.value

The value is set per environment with encore secret set, outside the repo. Encore supports Postgres, so a project on MySQL keeps its own database setup.

Try Encore →

How to choose

  • Encore when you want the agent to keep Django as it is and test against local Postgres, then deploy to your own AWS account without writing the ECS and RDS setup.
  • ECS and RDS by hand when a platform team already runs Django services on AWS with a shared module and pipeline.

Frequently asked questions

How do I deploy a Django app to AWS with an AI coding agent?

With Encore, the agent adds the encore-dev package, an encore.service.json and a small main.py adapter, declares the database with postgres.Database and builds DATABASES from its connection string. encore run starts Postgres locally, and Encore provisions the database and compute in your AWS account on deploy. Without Encore, the agent writes a Dockerfile, an ECS service, an RDS instance, Secrets Manager entries and IAM roles, and reads them in settings.py through environment variables.

Does Encore replace Django?

No. Django keeps its ORM, admin, migrations and URL routing. Encore is an infrastructure SDK added to the project, so it supplies the database connection and other resources and handles provisioning and deploys.

What should the agent check before a Django deploy?

Django's deployment checklist covers DEBUG, SECRET_KEY, ALLOWED_HOSTS and the HTTPS settings. With Encore, those values still live in settings.py and should come from the environment or secrets, and cloud access sits with Encore's IAM role, not the agent.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders