DEV Community

Dipak Prasad
Dipak Prasad

Posted on

Building a Production-Grade AWS 3-Tier Java Application (Hands-On)

This project implements a secure and scalable 3-tier architecture on AWS. The presentation layer uses an Application Load Balancer deployed in public subnets. The application layer consists of Spring Boot applications running on EC2 instances in private subnets and scaled via Auto Scaling. The database layer uses Amazon RDS deployed in private subnets. A Bastion Host provides secure administrative access, and a NAT Gateway enables outbound internet access for private instances.

This article walks through everything I built, step by step, and explains why each component exists.

What We’re Building

At the end of this project, the application looks like this:

User
 ↓
Route 53
 ↓
CloudFront
 ↓
Application Load Balancer
 ↓
EC2 Auto Scaling Group
 ↓            ↓
Redis Cache    RDS Proxy
                 ↓
        RDS MySQL + Read Replica
Enter fullscreen mode Exit fullscreen mode

The goal wasn’t just to “make it work”, but to make it:
Secure
Scalable
Highly available
Production-ready

PHASE 1: NETWORKING (FOUNDATION)

  1. Create VPC
  2. Create Subnets (8 total)
    • Public Subnets (2 total)
      • Used for Load Balancer, NAT Gateway, Bastion Host
    • Private App Subnets (2 total)
      • Used for EC2 Auto Scaling Group
    • Private DB Subnets (2 total)
      • Used for RDS, RDS Proxy, Read Replica
    • Private Cache Subnets (2 total)
      • Used for Redis (ElastiCache)
  3. Internet Gateway - Allows public subnets to access the internet.
    • Create Internet Gateway
    • Attach Internet Gateway to VPC
  4. NAT Gateway - Private subnets need outbound-only internet access.
    • Create a NAT Gateway in public subnet and allocate an elastic IP.
  5. Route Tables
    • Public Route Table
      • Route: '0.0.0.0/0 → Internet Gateway'
      • Subnet Associate: 'public-a', 'public-b'
    • Private Route Table
      • Route: '0.0.0.0/0' → 'NAT Gateway'
      • Subnet Associate: 'private-app-', 'private-db-', 'private-cache-*'
  6. Security Groups
    • ALB Security Group (alb-sg)
      • Inbound: '80, 443' from '0.0.0.0/0'
      • Outbound: 8080 to 'app-sg'
    • Bastion Security Group (bastion-sg)
      • Inbound: 'SSH (22)' 'from your IP'
      • Outbound: 'SSH' to 'app-sg'
    • App Security Group (app-sg)
      • Inbound: '8080' from 'alb-sg', '22' from 'bastion-sg'
      • Outbound: 'All'
    • DB Security Group (db-sg)
      • Inbound: '3306' from 'app-sg'
      • Outbound: 'Local'
    • Redis Security Group (redis-sg)
      • Inbound: '6379' from 'app-sg'
      • Outbound: 'Local'

PHASE 2: COMPUTE LAYER

  1. Create a Bastion Host - This is the only SSH entry point.

    • Subnet: public-a
    • Public IP: Enabled
    • SG: bastion-sg
  2. Create an Application Load Balancer

    • Type: Application
    • Scheme: Internet-facing
    • Subnets: public-a, public-b
    • SG: alb-sg
  3. Create a Target Group - ALB routes traffic to target groups, not directly to EC2.

    • Target type: Instance
    • Port: 8080
    • Health check path: /health
  4. Create a Launch Template

    • AMI: Ubuntu
    • Instance type: t3.micro
    • SG: app-sg
    • IAM Role: ec2-app-role
    • User data: {}
  5. Create an Auto Scaling Group

    • Subnets: private-app-a, private-app-b
    • Min: 1 | Desired: 2 | Max: 3
    • Attach ALB target group

PHASE 3: DATABASE LAYER

  1. Create DB Subnet Group (RDS must know which private subnets to use) and select private DB subnets.
  2. Create RDS MySQL database
  3. Create AWS Secret Manager for DB password and enable autamatic rotation.
  4. Create Read Replica
  5. Create RDS Proxy

PHASE 4: REDIS CACHE

  1. Create Cache Subnet Group and select private cache subnets
  2. Create Redis Cluster

PHASE 5: Cloudfront & Route53

  1. Request SSL Certificate
  2. Create CloudFront Distribution
  3. Create a hosted zone record

Source Code Link

To run the application:

git clone https://github.com/dipakprasad22/AWS-3tier-Java-Spring-Boot-App.git
mvn clean package
java -Xms256m -Xmx512m -jar app.jar
curl http://localhost:8080/health
http://<ALB-DNS-NAME>/hello
Enter fullscreen mode Exit fullscreen mode

Top comments (0)