django → aws · 2026 deployment and migration playbook

Migrate a Django app to AWS: the target architecture, the cutover, and who runs it.

A production Django app on AWS usually runs gunicorn or uvicorn in containers on ECS with Fargate behind a load balancer, with PostgreSQL on RDS or Aurora, ElastiCache (or SQS) for Celery, and S3 plus CloudFront for static and media. Your models and views do not change. The work is the Dockerfile, environment-driven settings, the Celery tier, deploy steps, and the database cutover.

compute target
ECS on Fargate
database
RDS or Aurora Postgres
code changes
config, not logic
TL;DR
  • The web tier (gunicorn for sync, uvicorn workers for async or Channels) runs as containers on ECS with Fargate behind an Application Load Balancer. Postgres moves to RDS or Aurora PostgreSQL. Celery's broker and Django's cache move to ElastiCache (or SQS for the broker). Static and media go to S3 and CloudFront via django-storages.
  • The Django-specific work: a Dockerfile, settings driven by environment variables with secrets in Secrets Manager, migrate and collectstatic as deploy steps (not at container boot), and Celery workers and beat as their own ECS services. None of it touches models or business logic.
  • The database cutover is the risky part; AWS DMS keeps RDS in sync so the switch is short. A vetted AWS partner can run it. MAP is meant for migrations with meaningful ongoing AWS spend, so a small Django app may not qualify; when the migration does, your matched partner files it: typically $50K to $150K for startups. Depends on the workload; AWS approves.
the trigger

IWhy teams move a Django app to AWS

Django apps arrive at AWS from a PaaS (Heroku, Render, DigitalOcean App Platform) or from a single VPS. The reasons rhyme.

Cost as you grow. A PaaS charges a premium for running the platform. Once you run several web processes, Celery workers, managed Postgres and Redis around the clock, buying the underlying services on AWS (Fargate, RDS, ElastiCache) and right-sizing them can cost less. It is not automatic: price both sides with your real usage before you decide.

The architecture Django apps need. A real deployment is a web tier, a Celery worker tier, a beat scheduler, Postgres, a broker and cache, and somewhere for static and media. ECS models each tier as its own service with its own scaling, inside your VPC.

Surrounding requirements. Private subnets for the database, IAM, multi-AZ failover, compliance controls and integration with S3, SQS, SES and KMS are first-class on AWS.

The counterpoint: AWS asks you to own more (networking, IAM, images, pipelines, monitoring). That is why many teams have a partner run the move.

where things land

IIThe target architecture, tier by tier

Database, broker, cache, static and media map almost one-to-one. The compute choice is the main decision.

Compute. Amazon ECS on Fargate is the usual home: serverless containers with VPC control, per-service scaling, a load balancer, and clean separation of web, workers and beat. For a simple web service, ECS Express Mode creates the Fargate service, load balancer and scaling from one image. (App Runner closed to new customers on April 30, 2026.) EKS is overkill for one Django app unless you already run Kubernetes.

Web server. gunicorn for synchronous apps (start around 2 × vCPU + 1 workers and tune with load tests), or gunicorn with uvicorn.workers.UvicornWorker for async views and Channels. The load balancer terminates TLS with an ACM certificate.

Database. RDS for PostgreSQL (like-for-like) or Aurora PostgreSQL (storage that grows on its own, faster failover, up to 15 readers). The ORM speaks PostgreSQL either way, so you only change DATABASES. Keep it in private subnets.

Celery. ElastiCache for Redis OSS or Valkey as broker and result backend, doubling as Django's cache. Or Amazon SQS as the broker to drop a stateful component (SQS is not a result backend). Each worker pool runs as its own ECS service; beat runs as a single-replica service so schedules do not double-fire.

Static and media. collectstatic to S3 behind CloudFront via django-storages, or WhiteNoise for small apps. User uploads must go to S3: container disks are ephemeral and there are several tasks.

the hands-on part

IIIDockerizing Django: server, settings and secrets

Turning the app into a production image and moving configuration into AWS-managed config is the most hands-on task.

The Dockerfile is short: a slim Python base, install from your lockfile, copy the project, run as a non-root user, start gunicorn or uvicorn. The same image serves every tier: the web service runs the server, the worker service overrides the command to celery -A proj worker, and beat overrides it to celery -A proj beat.

Drive settings from environment variables (DEBUG, ALLOWED_HOSTS, DATABASE_URL, CELERY_BROKER_URL, SECRET_KEY). Put real secrets in AWS Secrets Manager and plain config in SSM Parameter Store; ECS injects both into the task, so your code still reads os.environ and nothing sensitive is baked into an image.

Two production details: set ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS and SECURE_PROXY_SSL_HEADER for running behind a load balancer, and plan connection pooling (RDS Proxy or PgBouncer) because persistent connections across many autoscaled tasks can exhaust Postgres connections.

the deploy contract

IVMigrations and collectstatic in CI/CD, not at container boot

With several tasks starting in parallel behind a load balancer, running these at boot causes races and flaky deploys.

Run collectstatic at build time (into the image, or into S3). Run migrate as a single one-off ECS task per deploy, wait for it to succeed, then roll the web and worker services. Keep migrations backward-compatible (add before you remove) so old and new tasks can coexist during a rolling deploy.

the deploy sequence

1. Build the image and run collectstatic. 2. Push to ECR. 3. Run a one-off migrate task and wait. 4. Update the web service. 5. Update the worker and beat services.

the risky part

VThe database cutover: DMS, DNS and a short window

Everything else can be built and tested without touching production. The database cutover is the one moment that touches live data.

AWS Database Migration Service (DMS) does a full load into RDS or Aurora, then streams ongoing changes (CDC) where your source database allows it, so at cutover you switch to an already-current copy. Same engine, so no schema conversion. If CDC is not possible from your current host, or the database is small, use pg_dump and pg_restore inside a maintenance window and time a test run first.

The cutover: maintenance page, drain the last changes, pause beat and let workers finish, switch DATABASES and the broker and cache URLs, update Route 53 (TTL lowered a day ahead), check that writes land in RDS, leave maintenance. After a data-only load, re-sync Postgres sequences or the first inserts collide on primary keys. Keep the old environment as a rollback until you are confident.

who runs it, who funds it

VIWho runs the move, and who can fund it

You can do this yourself with the steps above. Many teams have a partner run the landing zone, the container and Celery setup, and the cutover.

Partner-filed funding: AWS says the Migration Acceleration Program (MAP) helps offset initial migration costs. It is built for migrations with meaningful ongoing AWS spend, so a single small Django app may not qualify. When the migration does qualify, your matched partner files it and AWS approves: typically $50K to $150K for startups. Depends on the workload; AWS approves. Activate credits are separate, and you apply for those yourself.

CloudRoute matches you with one vetted AWS partner. Startups pay CloudRoute nothing; partners pay CloudRoute a monthly membership plus 10% of AWS-approved funding.

Who files it
FundingWho files itAmountWhen it fits
Migration Acceleration Program (MAP)Your matched AWS partner$50K to $150K for startups. Depends on the workload; AWS approves.You are not on AWS yet and want to migrate.
AWS Activate FoundersFounder applies$1,000 to start, up to $5,000Self-funded startups with no investor or accelerator behind them.
AWS Activate PortfolioFounder appliesup to $200,000Startups backed by a VC firm, accelerator or angel investor that is an AWS Activate Provider.
Facts checked on October 10, 2026. AWS decides every application.
component by component

Django component to AWS service

Every Django building block, where it lands on AWS, what changes, and the effort. "Low" rows are config or backend swaps; "Medium" and "High" rows are the real work.

Django componentAWS serviceWhat changesEffort
WSGI web (gunicorn)ECS on Fargate plus ALB (ECS Express Mode for simple apps)Containerise; ALB terminates TLSMedium
ASGI, async, Channels (uvicorn)ECS on Fargate plus ALBuvicorn worker class; WebSocket settingsMedium
PostgreSQLRDS for PostgreSQL or Aurora PostgreSQLDATABASES endpoint; cutover via DMS or dump and restoreHigh (cutover)
Celery broker and resultsElastiCache (Redis OSS or Valkey) or SQSCELERY_BROKER_URL; or SQS transportMedium
Celery workersECS service per queueWorker process becomes its own serviceMedium
Celery beatSingle-replica ECS service, or EventBridge SchedulerRun exactly one beatLow
CacheElastiCacheCACHES backend to the ElastiCache endpointLow
Static filesS3 plus CloudFront (django-storages) or WhiteNoiseStorage backend; collectstatic in CILow
Media uploadsAmazon S3 (django-storages)Default storage to S3Low
Settings and secretsSSM Parameter Store and Secrets ManagerInjected as env vars by ECSLow
EmailAmazon SES (or your provider)EMAIL_BACKEND settingsLow
Domain and TLSRoute 53, ACM, CloudFrontDNS and a free certificateLow
The high-effort rows (the Postgres cutover, containerising, the Celery tier) are what a migration partner usually handles.
want this run for you?
Get matched with an AWS partner who runs your Django migration
Get matched free with a vetted AWS partner who can file it
how a match works

How a match works (example)

  1. You tell us about the work

    You fill in a short form: what you run today, what you want to move, test or build, your stage and your region.

  2. We pick one partner

    We read your answers and pick one vetted AWS consulting partner that fits the work, the stack and the region. We reply within 24 hours; your matched partner reaches out within 5 business days.

  3. The partner checks MAP funding

    Your matched partner scopes the migration with you. Then it checks whether the move qualifies for MAP (Migration Acceleration Program) funding. MAP is for teams that are not on AWS yet.

  4. The partner files, AWS decides

    If the work qualifies, the partner files the funding request with AWS. AWS reviews it and decides. The amount depends on the workload.

  5. You pay nothing

    CloudRoute is free for startups. Partners pay CloudRoute a monthly membership plus 10% of AWS-approved funding.

AWS Activate credits are separate, and you apply for them yourself. Use Activate Founders if no investor backs you. Use Activate Portfolio with the Org ID or invite from your VC, accelerator, incubator or angel group if it is an Activate Provider. A consulting partner cannot apply for Activate on your behalf.

faq

Common questions

What is the best way to deploy Django on AWS in 2026?
For a production app: gunicorn or uvicorn in containers on Amazon ECS with Fargate behind an Application Load Balancer, PostgreSQL on RDS or Aurora, ElastiCache (or SQS) for Celery, and S3 plus CloudFront for static and media via django-storages. For a simple web service with little background work, ECS Express Mode is the low-setup option; App Runner closed to new customers on April 30, 2026.
How do I run Celery workers and beat on AWS?
Run each worker pool as its own ECS service from the same image with the command set to celery worker, and beat as a single-replica service so periodic tasks fire once. Use ElastiCache as broker and result backend, or SQS as the broker. Ship logs to CloudWatch and alarm on queue depth.
Where should migrations and collectstatic run?
Not at container boot. Run collectstatic at build time and migrate as a one-off ECS task per deploy, then roll the services. Keep migrations backward-compatible so old and new tasks can coexist.
Do I need to change my Django code?
Mostly no. Postgres to RDS or Aurora is the same engine, so models, migrations, queries and the admin are unchanged. What you change is configuration: the Dockerfile, environment-driven settings, storage backends, and ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS and SECURE_PROXY_SSL_HEADER for running behind a load balancer.
How much downtime is there at the database cutover?
With DMS change data capture, a short pause to drain changes, switch settings and update DNS. Without it, the time a dump and restore takes, which you should measure on a copy first. Re-sync Postgres sequences after a data-only load.
Can AWS fund a Django migration?
Sometimes. MAP is filed by an AWS partner and is built for migrations with meaningful ongoing AWS spend, so a small app may not qualify. When the migration qualifies, your matched partner files it and AWS approves: typically $50K to $150K for startups. Depends on the workload; AWS approves.

Move your Django app to AWS with a partner who has done it before.

CloudRoute matches you with one vetted AWS partner who plans and runs the Django migration: ECS on Fargate, RDS or Aurora, ElastiCache for Celery, S3 and CloudFront, and the database cutover. The partner files MAP funding when the migration qualifies and AWS approves. CloudRoute is free for startups.

we reply within24 hours
partner-filed funding$50K to $150K
CloudRoute fee for startups$0