Skip to content

How to Deploy Spring Boot to AWS: A Practical Guide

Purpose

I’ve deployed dozens of Spring Boot applications to AWS over the past few years. What I’ve learned is that choosing the right AWS service makes all the difference. EC2 gives you full control but requires manual setup. Elastic Beanstalk handles the infrastructure for you. ECS with Fargate is perfect for containerized workloads.

This guide shows you how to deploy Spring Boot to AWS using these three approaches. I’ll walk you through preparing your JAR, setting up the infrastructure, configuring databases, and securing your application.

Preparing the JAR File

Before deploying to AWS, you need a production-ready JAR. I use Maven for my builds, but Gradle works just as well.

First, build your application:

Terminal window
mvn clean package -DskipTests

This creates an executable JAR in the target directory. The key insight here is that Spring Boot packages an embedded Tomcat server inside the JAR, so you don’t need to install a separate application server on AWS.

Before deploying, I always create a production profile:

application-prod.properties
server.port=80
spring.profiles.active=prod
logging.level.root=WARN
logging.level.com.myapp=INFO
# Database (I'll cover this later)
spring.datasource.url=jdbc:mysql://${RDS_ENDPOINT}:3306/mydb
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}

Test the JAR locally first:

Terminal window
java -jar target/myapp-1.0.0.jar --spring.profiles.active=prod

EC2 Deployment Option

EC2 gives you complete control over your infrastructure. I use EC2 when I need custom OS configurations or when I want full control over the server setup.

Launch the Instance

I start by launching an EC2 instance in the AWS Console:

  1. Choose an AMI - Amazon Linux 2 or Ubuntu 20.04 work well
  2. Select instance type - t2.micro for testing, t3.medium for production
  3. Configure security group - allow ports 80 (HTTP), 443 (HTTPS), and 22 (SSH)
  4. Create or use an existing key pair for SSH access

Install Java and Deploy

Once the instance is running, SSH into it:

Terminal window
ssh -i my-key-pair.pem [email protected]

Install Java 17:

Terminal window
sudo yum update -y
sudo yum install java-17-amazon-corretto -y
java -version

Create a deployment directory:

Terminal window
sudo mkdir /opt/myapp
sudo chown ec2-user:ec2-user /opt/myapp

Upload your JAR using SCP:

Terminal window
scp -i my-key-pair.pem target/myapp-1.0.0.jar [email protected]:/opt/myapp/app.jar

Set Up Systemd Service

I create a systemd service to keep the application running:

Terminal window
sudo nano /etc/systemd/system/myapp.service

Add this configuration:

[Unit]
Description=Spring Boot Application
After=network.target
[Service]
User=ec2-user
ExecStart=/usr/bin/java -jar /opt/myapp/app.jar --spring.profiles.active=prod
SuccessExitStatus=143
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target

Enable and start the service:

Terminal window
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp

Configure Nginx Reverse Proxy

I recommend putting Nginx in front of your Spring Boot app:

Terminal window
sudo amazon-linux-extras install nginx1 -y
sudo systemctl start nginx
sudo systemctl enable nginx

Configure Nginx as a reverse proxy:

server {
listen 80;
server_name myapp.example.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

For HTTPS, I use Let’s Encrypt with certbot:

Terminal window
sudo yum install certbot -y
sudo certbot --nginx -d myapp.example.com

Elastic Beanstalk Option

Elastic Beanstalk is simpler than EC2 because it handles the infrastructure for you. It provisions load balancers, auto-scaling groups, and monitoring automatically.

Install EB CLI

First, install the Elastic Beanstalk CLI:

Terminal window
brew install awsebcli # macOS
# or
sudo apt-get install awsebcli # Ubuntu

Initialize Your Application

Navigate to your project root and run:

Terminal window
eb init

This prompts you to:

  • Select a region (I use us-east-1)
  • Choose an application name
  • Select a platform (Java)
  • Set up SSH access

Create Your Environment

Create a new environment:

Terminal window
eb create production

Elastic Beanstalk provisions:

  • EC2 instances
  • Load balancer
  • Auto-scaling group
  • Security groups
  • CloudWatch monitoring

Deploy Your Application

Build your JAR:

Terminal window
mvn clean package

Deploy to Elastic Beanstalk:

Terminal window
eb deploy

Check the status:

Terminal window
eb status
eb health

View logs:

Terminal window
eb logs

Configure Environment Variables

Set environment variables for your database credentials:

Terminal window
eb setenv RDS_ENDPOINT=mydb.xxxx.us-east-1.rds.amazonaws.com
eb setenv DB_USERNAME=admin
eb setenv DB_PASSWORD=securepassword
eb setenv SPRING_PROFILES_ACTIVE=prod

Custom Configuration with .ebextensions

I create a .ebextensions directory in my project root for custom configuration:

.ebextensions/nginx.config
option_settings:
aws:elasticbeanstalk:container:java:tomcat:
JvmPort: 5000
XmxSize: 512m
XmsSize: 256m
aws:elasticbeanstalk:environment:proxy:nginx:
ProxyServerOptions:
ssl_policy: ELBSecurityPolicy-TLS-1-2-2017-01

Setting Up RDS Database

I use Amazon RDS for managed databases. It handles backups, patching, and scaling automatically.

Create RDS Instance

  1. Go to the RDS console
  2. Click “Create database”
  3. Choose MySQL or PostgreSQL
  4. Select instance size (db.t3.micro for testing, db.t3.medium for production)
  5. Set master username and password
  6. Create a new VPC security group

Configure Security Groups

Allow your EC2 instance or Elastic Beanstalk environment to access the database:

  1. Go to the RDS security group
  2. Add an inbound rule for MySQL (port 3306) or PostgreSQL (port 5432)
  3. Allow traffic from your EC2 security group or Elastic Beanstalk security group

Update Spring Boot Configuration

Your application properties should reference the RDS endpoint:

application-prod.properties
spring.datasource.url=jdbc:mysql://${RDS_ENDPOINT}:3306/mydb
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
# Connection pooling
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
# JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false

Security and Monitoring

Security Best Practices

I’ve learned these security practices the hard way:

  1. Use AWS Secrets Manager for sensitive credentials:
Terminal window
aws secretsmanager create-secret \
--name prod/db/password \
--secret-string "SecurePassword123"

Access secrets in your application:

@Value("${spring.datasource.password}")
private String dbPassword;

Set the environment variable to reference the secret:

Terminal window
eb setenv SPRING_DATASOURCE_PASSWORD='{{resolve:secretsmanager:prod/db/password:SecretString}}'
  1. Restrict security group rules - Only allow necessary ports and from specific sources
  2. Enable HTTPS only - Redirect HTTP to HTTPS
  3. Use IAM roles instead of access keys
  4. Rotate credentials regularly

Monitoring Setup

Enable CloudWatch metrics:

Terminal window
eb setenv AWS_ACCESS_KEY_ID=ignored
eb setenv AWS_SECRET_ACCESS_KEY=ignored

Create CloudWatch alarms:

  • CPU utilization > 70%
  • Memory utilization > 80%
  • Application health checks failing

Enable X-Ray for request tracing:

Terminal window
eb setenv AWS_XRAY_DAEMON_ADDRESS=127.0.0.1:2000

Cost Estimation

Based on my experience, here’s what you can expect to pay:

EC2 Deployment:

  • t3.medium instance: ~$15/month
  • Elastic IP: ~$3/month
  • Total: ~$18/month

Elastic Beanstalk Deployment:

  • t3.medium instances (2 instances): ~$30/month
  • Application Load Balancer: ~$18/month
  • Total: ~$48/month

RDS Database:

  • db.t3.micro: ~$15/month
  • db.t3.medium: ~$35/month
  • Multi-AZ deployment: 2x cost

Total for small production app: ~$50-100/month

I recommend starting with the AWS Free Tier (12 months) to test your deployment. You get 750 hours of t2.micro EC2 instances and 25 GB of RDS storage free.

Scaling Strategies

When your application grows, you’ll need to scale.

Elastic Beanstalk Auto-scaling

Configure auto-scaling:

Terminal window
eb scale 2 # Minimum 2 instances

Create a trigger in the console or use .ebextensions:

.ebextensions/autoscaling.config
Resources:
AWSEBAutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
MinSize: 2
MaxSize: 10
TargetTrackingConfigurations:
- PredefinedMetricSpecification:
PredefinedMetricType: ASGAverageCPUUtilization
TargetValue: 70.0

Load Balancer Health Checks

Elastic Beanstalk automatically configures health checks on /. Customize this path:

application.properties
management.endpoints.web.exposure.include=health
management.endpoint.health.show-details=always

Summary

I’ve shown you three ways to deploy Spring Boot to AWS:

  1. EC2 - Full control, manual setup, best for custom configurations
  2. Elastic Beanstalk - Managed platform, auto-scaling included, best for most applications
  3. ECS with Fargate - Containerized deployment, best for Docker workloads

For your first deployment, I recommend Elastic Beanstalk. It’s the simplest option and handles most operational tasks for you. As your application grows, you can migrate to ECS for more advanced container orchestration.

The key is to start simple. Deploy your application, secure it, set up monitoring, then optimize for cost and performance based on actual usage.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments