Building a Scalable Web Application on AWS: A Step-by-Step Guide

Building a Scalable Web Application on AWS: A Step-by-Step Guide

In this comprehensive guide, we'll walk through building an end-to-end scalable web application on AWS, leveraging a robust set of services to host a PHP-based "Guestbook" application. This project demonstrates how to utilize AWS's infrastructure for scalability, reliability, and efficiency, all configured via the AWS Management Console in the us-east-1 region. Whether you're a cloud beginner or a seasoned developer, this hands-on tutorial will help you understand AWS architecture in action.

Project Overview

The Guestbook app allows users to submit and view messages, stored in a MySQL database, with static assets in Amazon S3, shared storage via Amazon EFS, and metadata caching in DynamoDB. The application is hosted on EC2 instances, scaled via an Auto Scaling Group (ASG), and fronted by an Application Load Balancer (ALB). Here's the architecture:

  • Amazon RDS (MySQL): Stores guestbook messages.
  • Amazon DynamoDB: Caches metadata (e.g., message count) for performance.
  • Amazon EC2: Runs Apache + PHP, connects to RDS and DynamoDB, mounts EFS.
  • Amazon S3: Hosts static assets (CSS) and app code.
  • Amazon EFS: Provides shared storage for logs or uploads.
  • EC2 Auto Scaling: Scales instances (1-5) based on CPU utilization.
  • Elastic Load Balancing (ALB): Distributes traffic across instances.

Step-by-Step Implementation

Step 1: Set Up Amazon RDS MySQL Database


Article content

RDS provides a managed MySQL database for reliable message storage.

  1. Navigate to Amazon RDS in the AWS Console.
  2. Click Create database > Standard create > Select MySQL.
  3. Choose Free tier template (db.t3.micro).
  4. Configure: DB instance identifier: guestbook-db Master username: admin Master password: SecurePass123! (use a strong password) Storage: 20 GiB (General Purpose SSD, gp2) Public access: Yes (for setup; restrict later) VPC security group: Create rds-sg with inbound MySQL (port 3306) from 0.0.0.0/0 Database name: guestbook
  5. Create and wait for the status to become "Available."
  6. Note the RDS endpoint (e.g., guestbook-db.xxxxx.us-east-1.rds.amazonaws.com).

Why? RDS ensures a scalable, managed database separate from compute resources.

Step 2: Create DynamoDB Table for Caching


Article content

DynamoDB caches metadata like message counts to reduce RDS load.

  1. Go to DynamoDB > Create table.
  2. Set table name: guestbook-metadata, partition key: key (String).
  3. Use default settings (on-demand capacity).
  4. Create the table.

Why? DynamoDB's NoSQL capabilities offer fast reads for frequently accessed metadata.

Step 3: Set Up S3 Bucket for App Code and Static Files


Article content

S3 stores PHP code and static assets like CSS, with versioning and event notifications enabled.

  1. Navigate to S3 > Create bucket.
  2. Name: guestbook-app-bucket (unique), Region: us-east-1.
  3. Uncheck "Block all public access" for static hosting.
  4. Enable Bucket Versioning.
  5. Enable Static website hosting (index document: index.html).
  6. Create an event notification for "All object create events" (destination placeholder for demo).
  7. Upload two files: index.php: Handles form submission and displays messages. styles.css: Basic styling for the app.
  8. Make styles.css public using ACL.

Example index.php (simplified):

<?php
$host = 'guestbook-db.xxxxx.us-east-1.rds.amazonaws.com'; // Replace with RDS endpoint
$user = 'admin';
$pass = 'SecurePass123!'; // Replace with your password
$db = 'guestbook';
$conn = new mysqli($host, $user, $pass, $db);
if ($conn->connect_error) die("Connection failed: " . $conn->connect_error);

// Create table
$conn->query("CREATE TABLE IF NOT EXISTS messages (id INT AUTO_INCREMENT PRIMARY KEY, message TEXT, timestamp TIMESTAMP)");

// DynamoDB integration
require 'vendor/autoload.php';
use Aws\DynamoDb\DynamoDbClient;
$dynamodb = new DynamoDbClient(['region' => 'us-east-1', 'version' => 'latest']);

// Handle form submission
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $message = $_POST['message'];
    $conn->query("INSERT INTO messages (message) VALUES ('$message')");
    $dynamodb->putItem([
        'TableName' => 'guestbook-metadata',
        'Item' => ['key' => ['S' => 'message_count'], 'value' => ['N' => (string)getMessageCount($conn)]]
    ]);
}

// Function to get message count
function getMessageCount($conn) {
    global $dynamodb;
    try {
        $result = $dynamodb->getItem(['TableName' => 'guestbook-metadata', 'Key' => ['key' => ['S' => 'message_count']]]);
        if (isset($result['Item'])) return (int)$result['Item']['value']['N'];
    } catch (Exception $e) {}
    $result = $conn->query("SELECT COUNT(*) as count FROM messages");
    return $result->fetch_assoc()['count'];
}

// Display UI
echo "<html><head><link rel='stylesheet' href='styles.css'></head><body>";
echo "<h1>Guestbook</h1><p>Total messages: " . getMessageCount($conn) . "</p>";
echo "<form method='post'><input name='message' placeholder='Enter message'><button>Submit</button></form>";
$result = $conn->query("SELECT * FROM messages ORDER BY timestamp DESC");
while ($row = $result->fetch_assoc()) echo "<p>" . $row['message'] . " (" . $row['timestamp'] . ")</p>";
echo "</body></html>";
$conn->close();
?>
        

Example styles.css:

body { font-family: Arial; background: #f0f0f0; }
h1 { color: blue; }
        

Why? S3 is cost-effective for static content and app code distribution.

Step 4: Configure Amazon EFS for Shared Storage


Article content

EFS enables shared storage across EC2 instances for logs or uploads.

  1. Go to EFS > Create file system.
  2. Name: guestbook-efs, VPC: Default, Performance: General Purpose.
  3. Create mount targets in all default VPC subnets.
  4. Create security group efs-sg with inbound NFS (port 2049) from EC2 security group.

Why? EFS ensures consistent file access across scaled instances.

Step 5: Launch and Configure EC2 Instance


Article content

EC2 hosts the PHP app, tested as a template for scaling.

  1. Create security groups: web-sg: Inbound HTTP (80), SSH (22, your IP), NFS (2049, from efs-sg). alb-sg: Inbound HTTP (80) from anywhere.
  2. Launch instance: Name: guestbook-template AMI: Amazon Linux 2 Type: t3.micro Storage: 30 GiB gp3 Security group: web-sg User data script to install Apache, PHP, AWS SDK, and mount EFS:

#!/bin/bash
yum update -y
amazon-linux-extras install php8.0 -y
yum install httpd php-mysqlnd php-dom git -y
systemctl start httpd
systemctl enable httpd
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
mkdir /var/www/html/vendor
cd /var/www/html
composer require aws/aws-sdk-php
aws s3 cp s3://guestbook-app-bucket/index.php /var/www/html/index.php
aws s3 cp s3://guestbook-app-bucket/styles.css /var/www/html/styles.css
chown -R apache:apache /var/www/html
yum install amazon-efs-utils -y
mkdir /mnt/efs
mount -t efs fs-xxxxxxxx:/ /mnt/efs # Replace with EFS ID
echo "fs-xxxxxxxx:/ /mnt/efs efs defaults,_netdev 0 0" >> /etc/fstab
        

  1. Connect via EC2 Instance Connect and verify app functionality.

Why? EC2 provides the compute power for the web application.

Step 6: Create AMI for Scaling

An AMI ensures consistent instance launches in the ASG.

  1. From the EC2 instance, create an image: guestbook-ami.
  2. Enable "No reboot" and wait for "Available" status.

Step 7: Set Up Auto Scaling Group (ASG)


Article content

ASG scales EC2 instances based on demand.

  1. Go to EC2 > Auto Scaling groups > Create Auto Scaling group.
  2. Name: guestbook-asg.
  3. Create launch template using guestbook-ami, t3.micro, web-sg.
  4. Set desired capacity: 1, min: 1, max: 5.
  5. Add target tracking policy for CPU utilization (50%).

Why? ASG ensures the app scales dynamically with load.

Step 8: Configure Application Load Balancer (ALB)


Article content

ALB distributes traffic across instances.

  1. Go to EC2 > Load Balancers > Create Application Load Balancer.
  2. Name: guestbook-alb, Internet-facing, Default VPC, alb-sg.
  3. Add HTTP:80 listener, forward to target group guestbook-tg.
  4. Integrate with ASG.

Why? ALB ensures high availability and load distribution.

Step 9: Test the Application


Article content

  1. Access the ALB DNS in a browser, submit messages, and verify RDS/DynamoDB storage.
  2. Simulate load (e.g., stress --cpu 2 --timeout 300) to trigger scaling.
  3. Verify EFS by writing files across instances.
  4. Check S3 event notifications on uploads.

Why? Testing confirms end-to-end functionality and scalability.

Step 10: Clean Up

To avoid costs and respect sandbox limits:

  1. Delete ASG, ALB, AMI, RDS, DynamoDB table, S3 bucket, EFS, and security groups.

Key Takeaways

This project showcases AWS's power in building scalable, reliable web applications. By integrating RDS, DynamoDB, S3, EFS, EC2, Auto Scaling, and ALB, you create a robust system that handles dynamic workloads efficiently. Practice these steps in the AWS Console to deepen your cloud expertise!

To view or add a comment, sign in

Others also viewed

Explore topics