- Location:
app/beer_catalog/db.py - Problem: Using SQLite instead of PostgreSQL
- Code:
engine = create_engine("sqlite:///beers.db", echo=True) - Impact: Assignment requires PostgreSQL RDS, but app is configured for SQLite
- Fix Needed: Configure for PostgreSQL with environment variables
- Location:
app/beer_catalog/db.py - Problem: Hardcoded database connection string
- Impact: Violates 12-factor app principle #3 (Config)
- Fix Needed: Use environment variables for database configuration
- Location:
app/beer_catalog/app.py - Problem: No error handling in API endpoints
- Lines: 18-22, 25-35
- Impact: Application will crash on database errors or invalid input
- Fix Needed: Add proper error handling and validation
- Location:
app/beer_catalog/app.py - Problem: Manual session management without proper cleanup
- Impact: Potential memory leaks and connection pool exhaustion
- Fix Needed: Use context managers or dependency injection
- Location:
app/beer_catalog/app.pyline 27 - Problem: No validation for required fields or data types
- Code:
beer = Beer(name=data["name"], style=data.get("style"), abv=data.get("abv")) - Impact: Application will crash if "name" is missing
- Fix Needed: Add proper input validation
- Location:
app/beer_catalog/beer.pyline 12 - Problem: ABV stored as String instead of Float/Decimal
- Code:
abv = Column(String) - Impact: Can't perform numerical operations on ABV values
- Fix Needed: Change to Float or Decimal type
- Location:
app/beer_catalog/beer.py - Problem: No length constraints on String fields
- Impact: Potential database performance issues and data integrity problems
- Fix Needed: Add appropriate length constraints
- Location:
docker/Dockerfile - Problem: No environment variable configuration for database
- Impact: Container can't connect to external database
- Fix Needed: Add environment variable support
- Location:
docker/Dockerfile - Problem: Container runs as root user
- Impact: Security vulnerability
- Fix Needed: Create non-root user
- Location:
app/pyproject.toml - Problem: No PostgreSQL driver in dependencies
- Impact: Can't connect to PostgreSQL database
- Fix Needed: Add
psycopg2-binaryorasyncpg
- Location:
app/pyproject.toml - Problem: Poetry package configuration doesn't match actual structure
- Code:
packages = [{include = "app", from = "src"}] - Impact: Poetry won't install correctly
- Fix Needed: Fix package configuration
- Location:
terraform/main.tf - Problem: File is completely empty
- Impact: No infrastructure defined
- Fix Needed: Implement all required AWS resources
- Location:
terraform/versions.tf - Problem: PostgreSQL provider included but no PostgreSQL resources defined
- Impact: Unused provider dependency
- Fix Needed: Either use the provider or remove it
- Location:
app/beer_catalog/app.py - Problem: No health check endpoint for load balancer
- Impact: ECS service won't know if app is healthy
- Fix Needed: Add
/healthendpoint
- Location:
app/beer_catalog/app.py - Problem: No structured logging
- Impact: Difficult to debug in production
- Fix Needed: Add proper logging configuration
- Fix database configuration (SQLite → PostgreSQL)
- Add PostgreSQL driver dependency
- Implement environment variable configuration
- Add basic error handling
- Fix data types (ABV as Float)
- Add input validation
- Implement proper session management
- Add health check endpoint
- Fix Docker security (non-root user)
- Add logging configuration
- Fix Poetry configuration
- Add data constraints
- Implement Terraform resources
- Configure proper IAM roles
- Set up security groups
- Implement CI/CD pipeline
- 12-Factor App Compliance: Most issues violate 12-factor app principles
- SOLID Principles: Current code doesn't follow single responsibility principle
- Security: Multiple security issues need addressing
- Scalability: Current design won't scale in production
These "gotchas" are actually excellent learning opportunities:
- Database Migration: Learn how to migrate from SQLite to PostgreSQL
- Environment Configuration: Understand 12-factor app principles
- Error Handling: Learn proper error handling patterns
- Security: Understand container and application security
- Infrastructure as Code: Start from scratch with proper structure
- ECS tasks were repeatedly stopping with exit code 1.
- CloudWatch logs showed:
sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
- Health check endpoint was not responding; app was not running.
- The application was trying to connect to a PostgreSQL database at
localhostinside the container, but the actual database was running on AWS RDS in a private subnet. - The ECS task definition was only passing
DB_HOSTor missing the correctDATABASE_URLenvironment variable, so the app defaulted tolocalhost.
- Checked ECS task status:
- Noticed tasks were stopping quickly after launch.
- Enabled CloudWatch logging:
- Updated ECS task definition to send logs to CloudWatch for easier debugging.
- Reviewed CloudWatch logs:
- Found clear Python stack trace showing connection attempts to
localhost.
- Found clear Python stack trace showing connection attempts to
- Reviewed environment variables:
- Realized the app expected a
DATABASE_URLenv var, not justDB_HOST.
- Realized the app expected a
- Checked RDS endpoint and credentials:
- Confirmed the correct RDS endpoint, username, and password.
- Updated the ECS task definition in Terraform to set the
DATABASE_URLenvironment variable:environment = [ { name = "DATABASE_URL" value = "postgresql://beer_admin:${var.db_password}@${var.db_host}:5432/beer_catalog" } ]
- Added
db_hostas a Terraform variable and set it to the RDS endpoint. - Re-applied Terraform to update the ECS service and task definition.
- Verified the app was running and healthy by hitting the
/healthendpoint.
- Always check CloudWatch logs for ECS task failures—they provide detailed error messages.
- Ensure your app's environment variables match what the code expects (e.g.,
DATABASE_URL). - Use Terraform variables to avoid hardcoding sensitive or environment-specific values.
- ECS task definition changes require a new revision and service update.