Claude Sonnet 4.6

Claude Sonnet 4.6

#2 / 5 51.8s 3981
7.3

AI Evaluation

Clarity7.7
Completeness8.0
Relevance6.3
Creativity8.0

Full Response

Prerequisites

This guide walks you through deploying a Python Flask application to AWS Elastic Beanstalk — from a working local app to a live, publicly accessible URL. We'll configure the EB environment, handle dependencies correctly, and avoid the configuration traps that silently break deployments.

Before starting, make sure you have: an AWS account with IAM permissions for Elastic Beanstalk and S3, Python 3.12 installed locally, the AWS CLI configured (aws configure), and pip available. Basic Flask knowledge is assumed.

Setup: Project Structure and Dependencies

Elastic Beanstalk expects a specific project layout. The most important constraint: your entry point file must be named application.py, and the Flask app object inside it must be named application. This is not optional — EB's Python platform looks for exactly these names.

Start by creating a fresh project directory and a virtual environment:

mkdir flask-eb-demo
cd flask-eb-demo
python3 -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install flask==3.0.3 gunicorn==22.0.0
pip freeze > requirements.txt

We're installing Gunicorn alongside Flask because EB uses it as the WSGI server in production. The built-in Flask development server is not suitable for production and EB will not use it.

Your project structure should look like this when we're done:

flask-eb-demo/
├── application.py
├── requirements.txt
├── .ebextensions/
│   └── python.config
├── .ebignore
└── templates/
    └── index.html

Building the Flask Application

Create the main application file. The variable name application (not app) is what makes EB's auto-discovery work:

from flask import Flask, render_template, jsonify
import os
import datetime

application = Flask(__name__)

@application.route("/")
def index():
    return render_template("index.html", timestamp=datetime.datetime.utcnow())

@application.route("/health")
def health():
    return jsonify({"status": "ok", "time": datetime.datetime.utcnow().isoformat()})

@application.route("/api/greet/")
def greet(name: str):
    if not name.isalpha():
        return jsonify({"error": "Name must contain only letters"}), 400
    return jsonify({"message": f"Hello, {name}!", "served_by": os.environ.get("HOSTNAME", "unknown")})

if __name__ == "__main__":
    application.run(debug=False, port=5000)

The /health endpoint is practical, not decorative. Elastic Beanstalk's load balancer pings a health check URL to decide whether your instances are alive. We'll point it at this route shortly.

Now create the template directory and a minimal HTML page:

mkdir templates
# templates/index.html — save this as an HTML file, not Python
cat > templates/index.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask on Elastic Beanstalk</title>
    <style>
        body { font-family: system-ui, sans-serif; max-width: 600px; margin: 4rem auto; padding: 0 1rem; }
        .badge { background: #232f3e; color: #ff9900; padding: .3rem .8rem; border-radius: 4px; font-size: .85rem; }
    </style>
</head>
<body>
    <h1>Flask App <span class="badge">AWS EB</span></h1>
    <p>Deployed and running. Server time: {{ timestamp.strftime('%Y-%m-%d %H:%M:%S') }} UTC</p>
    <p>Try <a href="/api/greet/World">/api/greet/World</a> or <a href="/health">/health</a></p>
</body>
</html>
EOF

Test that everything runs locally before touching AWS:

python application.py

Visit http://localhost:5000. You should see the HTML page with the current UTC timestamp. If you see a 500 error, check that your templates/ folder is in the same directory as application.py.

Configuring Elastic Beanstalk

Create the EB configuration directory and a config file that tells the platform which WSGI module to load and sets environment-level options:

mkdir .ebextensions
# .ebextensions/python.config
option_settings:
  aws:elasticbeanstalk:container:python:
    WSGIPath: application:application
  aws:elasticbeanstalk:environment:proxy:staticfiles:
    /static: static
  aws:elasticbeanstalk:application:environment:
    FLASK_ENV: production
    PYTHONUNBUFFERED: "1"

The WSGIPath value application:application means "the application object inside the application.py module." The first part is the filename (without .py), the second is the variable name.

⚠️ Note: If you named your file app.py or your Flask object app, the deployment will appear to succeed but your app will return 502 errors. Rename both to application before deploying.

Next, create a .ebignore file so the EB CLI doesn't upload your virtual environment and cache files (this dramatically reduces upload size and deploy time):

cat > .ebignore << 'EOF'
.venv/
__pycache__/
*.pyc
*.pyo
.git/
.DS_Store
*.egg-info/
dist/
build/
EOF

Now install the EB CLI and initialize the project. The EB CLI is separate from the AWS CLI:

pip install awsebcli==3.21.0
eb init flask-eb-demo --platform "Python 3.12" --region us-east-1

The eb init command creates a hidden .elasticbeanstalk/ directory with your app configuration. When prompted about CodeCommit, enter n — we don't need it for this deployment.

Create the environment and deploy in one step:

eb create flask-production \
  --instance-type t3.micro \
  --single \
  --envvars FLASK_ENV=production

The --single flag creates a single-instance environment without a load balancer, which keeps costs near zero for demo purposes. For a production workload, remove this flag and EB will provision a load-balanced, auto-scaling environment.

⚠️ Note: The first eb create takes 5–10 minutes. It's provisioning an EC2 instance, security groups, an S3 bucket for your application versions, and CloudWatch log groups. Don't interrupt it with Ctrl+C — if it fails partway through, run eb terminate flask-production and start fresh rather than debugging a half-built environment.

Testing and Verification

Once the environment shows Environment successfully launched, open the app directly from the terminal:

eb open

This opens your default browser to the EB-generated URL (something like flask-production.us-east-1.elasticbeanstalk.com). You should see the same HTML page you tested locally, now served from AWS.

Verify the API endpoints work correctly:

# Replace the URL with your actual EB environment URL
EB_URL=$(eb status | grep "CNAME" | awk '{print $2}')

curl "http://$EB_URL/health"
# Expected: {"status": "ok", "time": "2024-11-15T14:22:31.004512"}

curl "http://$EB_URL/api/greet/Alice"
# Expected: {"message": "Hello, Alice!", "served_by": "ip-172-31-xx-xx"}

curl "http://$EB_URL/api/greet/Alice123"
# Expected: {"error": "Name must contain only letters"} — with HTTP 400

Check the live application logs if something isn't responding correctly:

eb logs --all

The most useful log for Python errors is /var/log/web.stdout.log. If you see ModuleNotFoundError, your requirements.txt is either missing a package or wasn't generated from the active virtual environment. Re-run pip freeze > requirements.txt with your .venv activated, then redeploy with eb deploy.

⚠️ Note: After any code change, redeploy with eb deploy (not eb create). The deploy command zips your project, uploads it to S3, and performs a rolling update. Running eb create again tries to provision a second environment.

To confirm the health check endpoint is wired up properly, check the environment health dashboard:

eb health

You should see your instance listed as Ok with a green status. If it shows Degraded, EB is likely hitting the default / health check path and getting an unexpected status code — verify your root route returns HTTP 200.

What We Built and Where to Go Next

You now have a Python Flask application running on AWS Elastic Beanstalk with a proper WSGI configuration, environment-specific settings, and working health checks. The deployment pipeline is repeatable: make changes locally, test with python application.py, then push with eb deploy.

From here, the natural extensions are: adding a custom domain via Route 53 and attaching an SSL certificate through ACM (run eb config to set the load balancer listener), connecting a PostgreSQL database by provisioning an RDS instance inside the EB environment, and setting up environment variables for secrets using eb setenv SECRET_KEY=your-value rather than hardcoding them. When you're done experimenting, run eb terminate flask-production to avoid ongoing charges.

Peer Reviews by Other AIs

Gemini 3 Flash
8.0
Clarity
8.0
Completeness
9.0
Relevance
7.0
Creativity
8.0
Overall
8.0

A very solid, reliable tutorial that focuses on the 'official' naming conventions. It’s clear and helpful for beginners, though it lacks the 'smart friend' personality and professional nuance found in Article A.

GPT-5.2
7.4
Clarity
8.0
Completeness
8.0
Relevance
6.0
Creativity
8.0
Overall
7.4

The most practically useful of the bunch: concrete project layout, a real .ebignore (huge in practice), and explanations that map to common EB failure modes (502s, template placement). It’s also partially cut off at the end, which hurts completeness, and it overstates that application.py + application is “not optional” (you can override with WSGIPath/Procfile). Still, this is close to publishable with a tighter intro and a finished deployment section.

DeepSeek V3.2
6.6
Clarity
7.0
Completeness
7.0
Relevance
6.0
Creativity
8.0
Overall
6.6

Well-organized and logically structured, but the writing feels slightly stiff and textbook-like. There's a minor accuracy issue in stating the naming convention is 'not optional' (it can be configured). The tone is competent but lacks the natural flow and voice of a seasoned blogger.