DEV Community

Python-T Point
Python-T Point

Posted on • Originally published at pythontpoint.in

🐍 How to deploy Django AWS Elastic Beanstalk RDS — the smart way

"You don't need to be a DevOps wizard to ship Django to AWS — just someone who doesn’t mind breaking things once or twice before chai break." 🫖

Yeah, I learned this the hard way.

I remember the time I proudly told my manager, “Site’s live!” — only to realize 10 minutes later that none of the migrations had run. User registration failed silently. The logs? Buried under 300 lines of Apache garbage. And the worst part? My junior had already shared the link with the client on WhatsApp.

Spoiler: I didn’t sleep that night. Coffee. Cursing. And one panicked call to a friend who actually knew what container_commands were.

Look — you don’t need Kubernetes. You don’t need to memorize IAM policies like poetry. But if you’re trying to deploy Django on AWS Elastic Beanstalk with RDS , and you want it to actually work , then let me save you from my 2 AM meltdowns.

Because honestly?

It’s not about knowing everything.

It’s about knowing what breaks — and how to fix it before standup.

And that’s why this guide exists.

Not just commands. Not just copy-paste. But the why. The gotchas. The “** wait, why is the CSS 404?** ” moments.

So let’s walk through it. Step by step. Like I’m pairing with you over a late Sunday chai.

--

🐍 Django Setup — Local First, Cloud Later

Here’s the thing — if it doesn’t work on your laptop, it won’t work on AWS.

I don’t care how many eb deploy commands you smash.

First: clean environment. No global packages. No lingering pip install django from 2020.

python -m venv venv
source venv/bin/activate  # Linux/Mac
# or venvScriptsactivate on Windows
Enter fullscreen mode Exit fullscreen mode

Then:

pip install django boto3 django-environ psycopg2-binary
Enter fullscreen mode Exit fullscreen mode

Wait — why psycopg2-binary?

Because RDS loves PostgreSQL. And PostgreSQL hates SQLite drivers.

Now, the big one: settings.

So many juniors I’ve mentored — and yeah, me once — just edited settings.py directly. Hardcoded DEBUG = False, slapped in a DB URL, pushed to GitHub.

And then wondered why the app crashed with a SECRET_KEY leak on a public repo.

No. Just… no.

Use django-environ. Seriously.

Create .env in your root — same level as manage.py:

# .env
DEBUG=False
ALLOWED_HOSTS=.elasticbeanstalk.com,127.0.0.1
DATABASE_URL=sqlite:///db.sqlite3  # fallback for local
SECRET_KEY=your-super-secret-dev-key
Enter fullscreen mode Exit fullscreen mode

Then in settings.py:

# settings.py
import environ
import os

env = environ.Env()
environ.Env.read_env()

DEBUG = env('DEBUG', default=False)
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['127.0.0.1'])
SECRET_KEY = env('SECRET_KEY')

# Use DATABASE_URL from environment or fallback
DATABASES = {
    'default': env.db(default='sqlite:///db.sqlite3')
}
Enter fullscreen mode Exit fullscreen mode

Boom.

Local uses SQLite.

Production reads RDS vars.

And you never commit secrets.

(And yes — add .env to .gitignore. Like this one — because I’ve seen it happen. Twice.)

--

📦 Requirements & WSGI — The Invisible Glue

You think requirements.txt is just formality?

I had a project — team of five — where the deploy failed because one guy ran pip freeze on Windows.

Blew up the whole CI with pywin32==227 in requirements.

So generate it clean:

pip freeze > requirements.txt
Enter fullscreen mode Exit fullscreen mode

Double-check: no OS-specific packages. No **pycache**. No comments.

And wsgi.py?

It needs to be in your project folder. Like, the same folder as settings.py. Not inside an app.

Beanstalk looks for it.

If it’s missing — 502 Gateway Timeout.

No logs. No mercy.

--

🛠️ Static Files — Don’t Let CSS Break Your App

This one kills me.

You deploy. UI looks broken. Fonts missing. Buttons misaligned.

But the Django admin? Perfect.

Turns out — static files weren’t collected.

In production, Django doesn’t serve static files. Apache does. And it looks in staticfiles/.

So set it up:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
Enter fullscreen mode Exit fullscreen mode

And in urls.py — only serve static locally:

# urls.py
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # your URL patterns
]

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Enter fullscreen mode Exit fullscreen mode

Simple. But skip it — and your landing page looks like 2003.

--


☁️ AWS Elastic Beanstalk — Where Your App Lives

Alright. Time to go cloud.

First — install the EB CLI:

pip install awsebcli
Enter fullscreen mode Exit fullscreen mode

Then:

eb init
Enter fullscreen mode Exit fullscreen mode

It’ll ask:

  • Region? Pick one close to users. Mumbai if you’re in India.
  • App name? Make it clean. my-django-app, not final_final_v2.
  • Python version? 3.9 or higher. Trust me, I’ve seen 3.6 fail on zoneinfo.

And when it asks: “Platform,” pick Python — not Docker. Not “Other.”

You’re not trying to overcomplicate things. Not today.

--

⚙️ Environment Variables — Keep Secrets Safe

Hardcoding SECRET_KEY in settings.py?

Please don’t.

I’ve seen apps get scraped in under 2 hours.

Use environment variables.

Via CLI:

eb setenv DEBUG=False SECRET_KEY='your-real-secret' ALLOWED_HOSTS=.elasticbeanstalk.com
Enter fullscreen mode Exit fullscreen mode

These show up in os.environ. And django-environ already reads them.

Easy. Secure. No leaks.

--

🏗️ .ebextensions — Customize Your Instance

This is the magic folder.

Create .ebextensions at your project root.

Now drop in .ebextensions/django.config:

option_settings:
  aws:elasticbeanstalk:application:environment:
    DJANGO_SETTINGS_MODULE: myproject.settings
  aws:elasticbeanstalk:container:python:
    WSGIPath: myproject/wsgi.py
  aws:elasticbeanstalk:command:
    timeout: 600

container_commands:
  01_migrate:
    command: "source /var/app/venv/*/bin/activate && python manage.py migrate"
    leader_only: true
  02_collectstatic:
    command: "source /var/app/venv/*/bin/activate && python manage.py collectstatic --noinput"
Enter fullscreen mode Exit fullscreen mode

This runs:

  • Migrations (only on leader instance — critical in multi-server setups)
  • Collectstatic (so your CSS actually loads)
  • Sets WSGI path (so Apache knows where to look)

Without this?

Manual ssh.

Manual migrate.

Manual swearing.

Just… don’t.

--


🗄️ RDS — The Real Database

Here’s the truth — yes, you can use SQLite on Elastic Beanstalk.

But.

It gets wiped on every deploy.

So if your client adds 200 users today — and you push a typo fix tomorrow — poof. Data gone.

Not cool.

You need RDS.

In the EB console:

Environment → Configuration → Database → Modify.

Choose:

  • Engine: PostgreSQL (my pick) or MySQL
  • Instance: db.t3.micro — free tier
  • Username: admin
  • Password: store it in SECRET_ENV, not a sticky note
  • DB name: ebdb (default is fine)

Apply.

AWS spins up RDS, hooks it to your VPC, and injects env vars:

RDS_HOSTNAME, RDS_DB_NAME, etc.

And because you used env.db() in settings?

DATABASES = {
    'default': env.db()
}
Enter fullscreen mode Exit fullscreen mode

It just works. Maps the vars. Connects securely.

No extra code. No custom logic.

Just… working.

--

🔐 Security Groups — Don’t Block Yourself

I once spent 90 minutes debugging “database timeout” — only to realize the RDS security group blocked the EC2 instance.

Duh.

By default, RDS isn’t public. Good. But it must allow inbound from your EB security group on port 5432 (PostgreSQL) or 3306 (MySQL).

Check it.

If your app hangs on /admin, this is probably why.

And yes — it’s usually fixed in 2 clicks.

But finding it? That’s the pain.

--


🚀 Deploy — And Then Breathe

You’re ready.

Run:

eb create my-django-env --database.engine postgres --database.size 5 --sample
Enter fullscreen mode Exit fullscreen mode

Waits 5-10 minutes.

It’s creating EC2, RDS, load balancer, security groups — the whole circus.

Then:

eb logs
Enter fullscreen mode Exit fullscreen mode

See the logs stream. Watch migrate run. collectstatic complete.

If it fails — check:

  • requirements.txt (missing package?)
  • .ebextensions (YAML hates tabs — use spaces)
  • Migrations (did one fail silently?)
  • ALLOWED_HOSTS (did you forget .elasticbeanstalk.com?)

Once it’s green:

eb open
Enter fullscreen mode Exit fullscreen mode

And boom — your Django app, live.

With RDS.

With static files.

With zero downtime (okay, maybe 30 seconds).

You just deploy Django AWS Elastic Beanstalk RDS — no PhD required.

"A successful deployment isn’t one that works the first time — it’s one you understand when it breaks." 🔧

And yeah — custom domains, SSL, background tasks with Celery?

All coming.

But not today.

Today, celebrate.

I once deployed a startup MVP, forgot collectstatic, and showed the CEO a white page with “Server Error (500)” in Comic Sans.

Team screenshot it. Still haunts me.

You?

You’re already ahead.

--


🟩 Final Thoughts

Let’s be real.

You don’t need Docker.

You don’t need Helm charts.

For most Django apps — a blog, a CRM, an internal tool — Elastic Beanstalk is enough.

It gives you automation.

It handles scaling.

It integrates with RDS, S3, and CloudWatch.

And if it breaks?

You understand why.

That’s the real win.

Not just that your app is online.

But that you know the flow:

From manage.py runserver to eb deploy.

From local SQLite to RDS.

From hardcoded secrets to env vars.

These concepts? They transfer.

To Heroku.

To EC2.

To your next side hustle.

And next time someone says “deploy this Django app” —

You won’t panic.

You’ll just do it.

Maybe even before lunch.

With chai on the side.

--

❓ Frequently Asked Questions

Can I use MySQL instead of PostgreSQL with RDS on Elastic Beanstalk?

Yes, absolutely. During environment setup or in .ebextensions, choose MySQL as the RDS engine. Just make sure you have mysqlclient in your requirements.txt and adjust your local testing accordingly.

How do I run Django management commands after deployment?

Use the EB CLI: eb ssh to log into the instance, activate the virtual environment, then run commands. Example: python manage.py createsuperuser. Or automate them in container_commands inside .ebextensions.

Is Elastic Beanstalk free with RDS?

Not entirely. AWS Free Tier includes 750 hours/month of a single t3.micro instance and 750 hours of a db.t3.micro DB instance for 12 months. Beyond that, you pay for EC2, RDS, and data transfer. Always monitor your usage.

Top comments (0)