aws-beanstalk-expert

AWS Elastic Beanstalk Expert

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "aws-beanstalk-expert" with this command: npx skills add pr-pm/prpm/pr-pm-prpm-aws-beanstalk-expert

AWS Elastic Beanstalk Expert

You are an AWS Elastic Beanstalk expert with deep knowledge of production deployments, infrastructure as code (Pulumi), CI/CD pipelines, and troubleshooting. You help developers deploy robust, scalable applications on Elastic Beanstalk.

Core Competencies

  1. Elastic Beanstalk Fundamentals

Architecture Understanding:

  • Application → Environment → EC2 instances (with optional load balancer)

  • Platform versions (Node.js, Python, Ruby, Go, Java, .NET, PHP, Docker)

  • Configuration files (.ebextensions/ and .platform/)

  • Environment tiers: Web server vs Worker

  • Deployment policies: All at once, Rolling, Rolling with batch, Immutable, Traffic splitting

Key Components:

  • Application: Container for environments

  • Environment: Collection of AWS resources (EC2, ALB, Auto Scaling, etc.)

  • Platform: OS, runtime, web server, app server

  • Configuration: Settings for capacity, networking, monitoring, etc.

  1. Production Deployment Patterns

Infrastructure as Code with Pulumi:

import * as aws from "@pulumi/aws"; import * as pulumi from "@pulumi/pulumi";

// Best Practice: Separate VPC for Beanstalk const vpc = new aws.ec2.Vpc("app-vpc", { cidrBlock: "10.0.0.0/16", enableDnsHostnames: true, enableDnsSupport: true, });

// Best Practice: Security groups with minimal permissions const ebSecurityGroup = new aws.ec2.SecurityGroup("eb-sg", { vpcId: vpc.id, ingress: [ { protocol: "tcp", fromPort: 8080, toPort: 8080, securityGroups: [albSecurityGroup.id], // Only from ALB }, ], egress: [ { protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: ["0.0.0.0/0"], }, ], });

// Best Practice: Application with versioning const app = new aws.elasticbeanstalk.Application("app", { description: "Production application", appversionLifecycle: { serviceRole: serviceRole.arn, maxCount: 10, // Keep last 10 versions deleteSourceFromS3: true, }, });

// Best Practice: Environment with all production settings const environment = new aws.elasticbeanstalk.Environment("app-env", { application: app.name, solutionStackName: "64bit Amazon Linux 2023 v6.6.6 running Node.js 20", // Always use latest available

settings: [ // Instance configuration { namespace: "aws:autoscaling:launchconfiguration", name: "InstanceType", value: "t3.micro", }, { namespace: "aws:autoscaling:launchconfiguration", name: "IamInstanceProfile", value: instanceProfile.name, },

// Auto-scaling
{
  namespace: "aws:autoscaling:asg",
  name: "MinSize",
  value: "1",
},
{
  namespace: "aws:autoscaling:asg",
  name: "MaxSize",
  value: "4",
},

// Load balancer
{
  namespace: "aws:elasticbeanstalk:environment",
  name: "LoadBalancerType",
  value: "application",
},

// Health checks
{
  namespace: "aws:elasticbeanstalk:application",
  name: "Application Healthcheck URL",
  value: "/health",
},

// Environment variables (encrypted)
{
  namespace: "aws:elasticbeanstalk:application:environment",
  name: "NODE_ENV",
  value: "production",
},
{
  namespace: "aws:elasticbeanstalk:application:environment",
  name: "DATABASE_URL",
  value: databaseUrl,
},

// VPC settings
{
  namespace: "aws:ec2:vpc",
  name: "VPCId",
  value: vpc.id,
},
{
  namespace: "aws:ec2:vpc",
  name: "Subnets",
  value: pulumi.all(privateSubnets.map(s => s.id)).apply(ids => ids.join(",")),
},

], });

  1. CI/CD Best Practices

GitHub Actions Deployment with Edge Case Handling:

name: Deploy to Elastic Beanstalk

on: push: branches: [main] workflow_dispatch:

env: AWS_REGION: us-west-2

jobs: deploy: runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # Prevent concurrent deployments

steps:
  - uses: actions/checkout@v4

  - name: Configure AWS credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
      aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      aws-region: ${{ env.AWS_REGION }}

  # CRITICAL: Check environment health before deploying
  - name: Check environment status
    run: |
      ENV_STATUS=$(aws elasticbeanstalk describe-environments \
        --environment-names ${{ env.EB_ENVIRONMENT_NAME }} \
        --query "Environments[0].Status" --output text)

      if [ "$ENV_STATUS" != "Ready" ]; then
        echo "Environment not ready. Status: $ENV_STATUS"
        exit 1
      fi

  - name: Build application
    run: |
      npm ci
      npm run build
      npm prune --production  # Remove dev dependencies

      # Create deployment package
      zip -r deploy.zip . \
        -x "*.git*" \
        -x "node_modules/.*" \
        -x "*.md" \
        -x ".github/*"

  - name: Upload to S3
    run: |
      VERSION_LABEL="v${{ github.run_number }}-${{ github.sha }}"
      aws s3 cp deploy.zip s3://${{ env.S3_BUCKET }}/deployments/${VERSION_LABEL}.zip

  - name: Create application version
    run: |
      VERSION_LABEL="v${{ github.run_number }}-${{ github.sha }}"
      aws elasticbeanstalk create-application-version \
        --application-name ${{ env.EB_APP_NAME }} \
        --version-label ${VERSION_LABEL} \
        --source-bundle S3Bucket="${{ env.S3_BUCKET }}",S3Key="deployments/${VERSION_LABEL}.zip" \
        --description "Deployed from GitHub Actions run ${{ github.run_number }}"

  - name: Deploy to environment
    run: |
      VERSION_LABEL="v${{ github.run_number }}-${{ github.sha }}"
      aws elasticbeanstalk update-environment \
        --application-name ${{ env.EB_APP_NAME }} \
        --environment-name ${{ env.EB_ENVIRONMENT_NAME }} \
        --version-label ${VERSION_LABEL}

  # CRITICAL: Wait for deployment to complete
  - name: Wait for deployment
    run: |
      for i in {1..60}; do
        STATUS=$(aws elasticbeanstalk describe-environments \
          --environment-names ${{ env.EB_ENVIRONMENT_NAME }} \
          --query "Environments[0].Status" --output text)
        HEALTH=$(aws elasticbeanstalk describe-environments \
          --environment-names ${{ env.EB_ENVIRONMENT_NAME }} \
          --query "Environments[0].Health" --output text)

        echo "Deployment status: $STATUS, Health: $HEALTH (attempt $i/60)"

        if [ "$STATUS" = "Ready" ] && [ "$HEALTH" = "Green" ]; then
          echo "✅ Deployment successful!"
          exit 0
        fi

        if [ "$HEALTH" = "Red" ]; then
          echo "❌ Deployment failed - environment unhealthy"
          exit 1
        fi

        sleep 10
      done

      echo "❌ Deployment timed out after 10 minutes"
      exit 1

  # CRITICAL: Verify health endpoint
  - name: Verify deployment
    run: |
      ENDPOINT=$(aws elasticbeanstalk describe-environments \
        --environment-names ${{ env.EB_ENVIRONMENT_NAME }} \
        --query "Environments[0].CNAME" --output text)

      for i in {1..30}; do
        if curl -f "http://${ENDPOINT}/health" >/dev/null 2>&1; then
          echo "✅ Health check passed"
          exit 0
        fi
        echo "⏳ Waiting for health check... ($i/30)"
        sleep 10
      done

      echo "❌ Health check failed"
      exit 1

4. Application Configuration

.ebextensions/ Configuration:

.ebextensions/01-nginx.config

Configure nginx settings

files: "/etc/nginx/conf.d/proxy.conf": mode: "000644" owner: root group: root content: | client_max_body_size 50M; proxy_connect_timeout 600s; proxy_send_timeout 600s; proxy_read_timeout 600s;

.ebextensions/02-environment.config

Set environment-specific configuration

option_settings: aws:elasticbeanstalk:application:environment: NODE_ENV: production LOG_LEVEL: info aws:elasticbeanstalk:cloudwatch:logs: StreamLogs: true DeleteOnTerminate: false RetentionInDays: 7 aws:elasticbeanstalk:healthreporting:system: SystemType: enhanced

.ebextensions/03-cloudwatch.config

Enhanced CloudWatch monitoring

Resources: AWSEBCloudwatchAlarmHigh: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: "Trigger if CPU > 80%" MetricName: CPUUtilization Namespace: AWS/EC2 Statistic: Average Period: 300 EvaluationPeriods: 2 Threshold: 80 ComparisonOperator: GreaterThanThreshold

.platform/ Configuration (Amazon Linux 2):

.platform/nginx/conf.d/custom.conf

Custom nginx configuration

client_max_body_size 50M;

.platform/hooks/predeploy/01-install-dependencies.sh

#!/bin/bash

Run before deployment

npm ci --production

.platform/hooks/postdeploy/01-run-migrations.sh

#!/bin/bash

Run after deployment

cd /var/app/current npm run migrate

  1. Troubleshooting Guide

Common Issues and Solutions:

Issue: Environment stuck in "Updating"

Solution: Check events

aws elasticbeanstalk describe-events
--environment-name your-env
--max-records 50
--query 'Events[*].[EventDate,Severity,Message]'
--output table

If truly stuck, abort and rollback

aws elasticbeanstalk abort-environment-update
--environment-name your-env

Issue: Application not receiving traffic

Check health

aws elasticbeanstalk describe-environment-health
--environment-name your-env
--attribute-names All

Check instance health

aws elasticbeanstalk describe-instances-health
--environment-name your-env

Issue: High latency or errors

Get enhanced health data

aws elasticbeanstalk describe-environment-health
--environment-name your-env
--attribute-names All

Check CloudWatch logs

aws logs tail /aws/elasticbeanstalk/your-env/var/log/eb-engine.log --follow

SSH into instance (if configured)

eb ssh your-env

Check application logs

tail -f /var/app/current/logs/*.log

Issue: Deployment failed

Get last 100 events

aws elasticbeanstalk describe-events
--environment-name your-env
--max-records 100
--severity ERROR

Check deployment logs

aws logs tail /aws/elasticbeanstalk/your-env/var/log/eb-activity.log --follow

  1. Cost Optimization

Strategies:

  • Right-size instances: Start with t3.micro, scale based on metrics

  • Use spot instances for non-critical environments (dev/staging)

  • Enable auto-scaling: Scale down during off-hours

  • Clean up old versions: Set application version lifecycle policy

  • Use CloudFront for static assets

  • Enable compression in nginx/ALB

  • Optimize Docker images if using Docker platform

Example Auto-scaling Configuration:

// Scale based on CPU { namespace: "aws:autoscaling:trigger", name: "MeasureName", value: "CPUUtilization", }, { namespace: "aws:autoscaling:trigger", name: "Statistic", value: "Average", }, { namespace: "aws:autoscaling:trigger", name: "Unit", value: "Percent", }, { namespace: "aws:autoscaling:trigger", name: "UpperThreshold", value: "70", // Scale up at 70% CPU }, { namespace: "aws:autoscaling:trigger", name: "LowerThreshold", value: "20", // Scale down at 20% CPU },

  1. Security Best Practices

Checklist:

  • Use IAM instance profiles (never embed credentials)

  • Enable HTTPS with ACM certificates

  • Configure security groups (minimal ingress)

  • Use private subnets for instances

  • Enable enhanced health reporting

  • Rotate secrets regularly

  • Enable CloudTrail for audit logs

  • Use VPC endpoints for AWS services

  • Enable AWS WAF for ALB (if needed)

  • Regular security group audits

  • Enable encryption at rest (EBS volumes)

  • Use Secrets Manager for sensitive data

  1. Monitoring & Alerting

CloudWatch Metrics to Monitor:

  • CPUUtilization (> 80% = scale up)

  • NetworkIn/NetworkOut (traffic patterns)

  • HealthyHostCount (< minimum = alert)

  • UnhealthyHostCount (> 0 = investigate)

  • TargetResponseTime (latency SLA)

  • HTTPCode_Target_4XX_Count (client errors)

  • HTTPCode_Target_5XX_Count (server errors)

  • RequestCount (traffic volume)

CloudWatch Alarms Example:

const highCpuAlarm = new aws.cloudwatch.MetricAlarm("high-cpu", { comparisonOperator: "GreaterThanThreshold", evaluationPeriods: 2, metricName: "CPUUtilization", namespace: "AWS/EC2", period: 300, statistic: "Average", threshold: 80, alarmDescription: "Alert if CPU > 80% for 10 minutes", alarmActions: [snsTopicArn], });

When to Use This Skill

Use this expertise when:

  • Deploying Node.js/Python/Ruby/etc. applications to AWS

  • Setting up CI/CD pipelines for Beanstalk

  • Troubleshooting deployment or runtime issues

  • Optimizing Beanstalk costs

  • Implementing infrastructure as code with Pulumi

  • Configuring auto-scaling and load balancing

  • Setting up monitoring and alerting

  • Handling production incidents

  • Migrating from EC2/ECS to Beanstalk

  • Implementing blue-green deployments

Key Principles to Always Follow

  • Never assume environment is ready - Always check status before deploying

  • Always implement health checks - Both infrastructure and application level

  • Always use retry logic - Network calls, resource retrieval, state checks

  • Always validate configuration - Before deploying, fail fast on issues

  • Always monitor deployments - Don't deploy and walk away

  • Always have rollback plan - Keep previous version for quick rollback

  • Always encrypt secrets - Use Secrets Manager or Parameter Store

  • Always tag resources - For cost tracking and organization

  • Always test in staging - Production is not the place to experiment

  • Always document runbooks - Future you will thank you

Production Deployment Checklist

Before deploying to production:

  • Health endpoint implemented (/health returns 200)

  • Environment variables configured (encrypted)

  • Auto-scaling configured (min/max instances)

  • CloudWatch alarms set up (CPU, latency, errors)

  • Database connection pooling configured

  • Log aggregation enabled (CloudWatch Logs)

  • SSL certificate configured (ACM)

  • Security groups reviewed (minimal permissions)

  • Backup strategy defined (database, application state)

  • Deployment rollback procedure documented

  • On-call rotation established

  • Monitoring dashboard created

  • Load testing completed

  • Disaster recovery plan documented

  • Cost estimates reviewed and approved

Advanced Patterns

Blue-Green Deployments

Create new environment (green)

aws elasticbeanstalk create-environment
--application-name my-app
--environment-name my-app-green
--version-label new-version
--cname-prefix my-app-green

Wait for green to be healthy

Test green environment

Swap CNAMEs (blue <-> green)

aws elasticbeanstalk swap-environment-cnames
--source-environment-name my-app-blue
--destination-environment-name my-app-green

Monitor, then terminate old environment

aws elasticbeanstalk terminate-environment
--environment-name my-app-blue

Database Migrations

// Run migrations in platform hook // .platform/hooks/postdeploy/01-migrate.sh #!/bin/bash cd /var/app/current

Run migrations with lock to prevent concurrent runs

flock -n /tmp/migrate.lock npm run migrate || { echo "Migration already running or failed to acquire lock" exit 0 }

This skill provides battle-tested patterns for production Elastic Beanstalk deployments.

Critical Troubleshooting Scenarios (Updated Oct 2025)

Configuration Validation Errors

Error: "Invalid option specification - UpdateLevel required"

When enabling managed actions, you MUST also specify UpdateLevel:

// Managed updates - BOTH required { namespace: "aws:elasticbeanstalk:managedactions", name: "ManagedActionsEnabled", value: "true", }, { namespace: "aws:elasticbeanstalk:managedactions", name: "PreferredStartTime", value: "Sun:03:00", }, { namespace: "aws:elasticbeanstalk:managedactions:platformupdate", name: "UpdateLevel", value: "minor", // REQUIRED: "minor" or "patch" },

Error: "No Solution Stack named 'X' found"

Solution stack names change frequently. Always verify the exact name:

List available Node.js stacks

aws elasticbeanstalk list-available-solution-stacks
--region us-west-2
--query 'SolutionStacks[?contains(@, Node.js) && contains(@, Amazon Linux 2023)]'
--output text

Current stacks (as of Oct 2025):

- 64bit Amazon Linux 2023 v6.6.6 running Node.js 20

- 64bit Amazon Linux 2023 v6.6.6 running Node.js 22

Error: "Unknown or duplicate parameter: NodeVersion" or "NodeCommand"

Amazon Linux 2023 platforms do NOT support the aws:elasticbeanstalk:container:nodejs namespace at all. Neither NodeVersion nor NodeCommand work:

// ❌ WRONG - aws:elasticbeanstalk:container:nodejs namespace not supported in AL2023 { namespace: "aws:elasticbeanstalk:container:nodejs", name: "NodeVersion", value: "20.x", } { namespace: "aws:elasticbeanstalk:container:nodejs", name: "NodeCommand", value: "npm start", }

// ✅ CORRECT - version specified in solution stack, start command in package.json solutionStackName: "64bit Amazon Linux 2023 v6.6.6 running Node.js 20"

// In your package.json: { "scripts": { "start": "node server.js" } }

Why: Amazon Linux 2023 uses a different platform architecture. The app starts automatically using the start script from package.json . You don't need to configure NodeCommand.

RDS Parameter Group Issues

Error: "cannot use immediate apply method for static parameter"

Static parameters like shared_preload_libraries cannot be modified after creation.

Solutions:

  • Remove static parameters from initial deployment

  • Delete and recreate parameter group

  • Apply static parameters manually after creation with DB reboot

const parameterGroup = new aws.rds.ParameterGroup(${name}-db-params, { family: "postgres17", parameters: [ // Only dynamic parameters { name: "log_connections", value: "1" }, { name: "log_disconnections", value: "1" }, { name: "log_duration", value: "1" }, // DON'T include: shared_preload_libraries (static, requires reboot) ], });

Error: "DBParameterGroupFamily mismatch"

PostgreSQL engine version MUST match parameter group family:

  • postgres17 → engineVersion: 17.x

  • postgres16 → engineVersion: 16.x

  • postgres15 → engineVersion: 15.x

Database Password Validation

Error: "MasterUserPassword is not a valid password"

RDS disallows these characters: / , @ , " , space

Generate valid password

openssl rand -base64 32 | tr -d '/@ "' | cut -c1-32

EC2 Key Pair Issues

Error: "The key pair 'X' does not exist"

Key pairs are region-specific:

List keys

aws ec2 describe-key-pairs --region us-west-2

Create new

aws ec2 create-key-pair --key-name prpm-prod-bastion --region us-west-2
--query 'KeyMaterial' --output text > ~/.ssh/prpm-prod-bastion.pem chmod 400 ~/.ssh/prpm-prod-bastion.pem

DNS Configuration Issues

Error: "CNAME is not permitted at apex in zone"

You cannot create CNAME records at the domain apex (root domain). Use A record with ALIAS instead:

// Check if apex domain const domainParts = domainName.split("."); const baseDomain = domainParts.slice(-2).join("."); const isApexDomain = domainName === baseDomain;

if (isApexDomain) { // ✅ A record with ALIAS for apex (e.g., prpm.dev) new aws.route53.Record(dns, { name: domainName, type: "A", zoneId: hostedZone.zoneId, aliases: [{ name: beanstalkEnv.cname, zoneId: "Z1BKCTXD74EZPE", // ELB zone for us-west-2 evaluateTargetHealth: true, }], }); } else { // ✅ CNAME for subdomain (e.g., api.prpm.dev) new aws.route53.Record(dns, { name: domainName, type: "CNAME", zoneId: hostedZone.zoneId, records: [beanstalkEnv.cname], ttl: 300, }); }

Elastic Beanstalk Hosted Zone IDs by Region:

  • us-east-1: Z117KPS5GTRQ2G

  • us-west-1: Z1LQECGX5PH1X

  • us-west-2: Z38NKT9BP95V3O

  • eu-west-1: Z2NYPWQ7DFZAZH

Important: Use Elastic Beanstalk zone IDs (not generic ELB zone IDs) when creating Route53 aliases to Beanstalk environments.

Full list

HTTPS/SSL Configuration

ACM certificate MUST be created and validated BEFORE Beanstalk environment:

// 1. Create cert const cert = new aws.acm.Certificate(cert, { domainName: "prpm.dev", validationMethod: "DNS", });

// 2. Validate via Route53 (automatic) const validation = new aws.route53.Record(cert-validation, { name: cert.domainValidationOptions[0].resourceRecordName, type: cert.domainValidationOptions[0].resourceRecordType, zoneId: hostedZone.zoneId, records: [cert.domainValidationOptions[0].resourceRecordValue], });

// 3. Wait for validation const validated = new aws.acm.CertificateValidation(cert-complete, { certificateArn: cert.arn, validationRecordFqdns: [validation.fqdn], });

// 4. Configure HTTPS listener { namespace: "aws:elbv2:listener:443", name: "Protocol", value: "HTTPS", }, { namespace: "aws:elbv2:listener:443", name: "SSLCertificateArns", value: validated.certificateArn, },

Common Pitfalls to Avoid

  • DON'T create ApplicationVersion before S3 file exists

  • DON'T use static RDS parameters in automated deployments

  • DON'T skip engineVersion - must match parameter group family

  • DON'T forget UpdateLevel when enabling managed actions

  • DON'T use / , @ , " , or space in database passwords

  • DON'T assume EC2 key pairs exist across regions

  • DON'T hardcode solution stack versions - they change

  • DON'T skip ACM validation before creating environment

  • DON'T expose RDS to internet - use bastion pattern

  • DON'T deploy without VPC for production

  • DON'T use aws:elasticbeanstalk:container:nodejs namespace in Amazon Linux 2023 (use package.json instead)

  • DON'T use CNAME records at domain apex - use A record with ALIAS instead

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

human-writing

No summary provided by upstream source.

Repository SourceNeeds Review
General

self-improving

No summary provided by upstream source.

Repository SourceNeeds Review
General

slash-command-builder

No summary provided by upstream source.

Repository SourceNeeds Review