Deploying a web application in AWS can seem daunting, but with the right steps, it becomes a straightforward process. This guide walks through building and deploying a serverless web app using Amazon S3, API Gateway, Lambda, and DynamoDB. By the end of this tutorial, you’ll have a fully functional app while avoiding common pitfalls like denied access and CORS errors.
The Overall Architecture
The architecture for this project includes the following AWS services:
- Amazon S3: Hosts the static website files.
- API Gateway: Manages backend requests and connects the frontend to backend services.
- AWS Lambda: Executes backend logic and interacts with other AWS services.
- DynamoDB: Stores application data efficiently and scalably.
The final product will be a simple banking web app that allows users to check their account balance securely and quickly—all within a serverless infrastructure.
Step 1: Configure an S3 Bucket for Website Hosting
Set Up the S3 Bucket
- Create an S3 bucket in the AWS Management Console.
- Navigate to the Permissions tab and click Edit under “Block public access.” Uncheck Block all public access and save changes.
Add a Bucket Policy
To make your website files accessible, add the following JSON policy under the Bucket Policy section:
json{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}
Configure CORS Settings
Set up Cross-Origin Resource Sharing (CORS) to allow requests from any domain during development:
json[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "POST"],
"AllowedOrigins": ["*"]
}
]
Enable Static Website Hosting
- Go to the Properties tab of your bucket.
- Enable static website hosting and specify
index.html
as the default document.
Your S3 bucket is now ready to host static files for your web app! 🎉
Step 2: Build the Website
Create Basic Files
At minimum, you’ll need an index.html
file for your website’s structure and optional CSS/JavaScript files for styling and functionality. For example:
xml<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Balance Checker</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>Balance Checker</h1>
<div class="input-group">
<label for="accountIdForBalance">Account ID:</label>
<input type="text" id="accountIdForBalance" placeholder="Enter account ID">
<button id="checkBalance">Check Balance</button>
</div>
<div id="balanceResult"></div>
</div>
<script src="script.js"></script>
</body>
</html>
Upload Files to S3
Once your files are ready, upload them to your S3 bucket using the AWS Management Console or CLI.
Step 3: Configure DynamoDB for Data Storage
Create a DynamoDB Table
- In the DynamoDB console, create a table named
accounts
. - Set
account_id
as the primary key and add attributes likebalance
,user_name
, anduser_address
. Use On-Demand mode for simplicity.
Add Sample Data
Add test items directly in DynamoDB using the “Explore Table Items” option.
Step 4: Deploy an AWS Lambda Function
Lambda Function Code (Python)
Create a Lambda function to fetch account balances from DynamoDB:
pythonimport json
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('accounts')
def lambda_handler(event, context):
account_id = event['accountId']
response = table.get_item(Key={'account_id': account_id})
if 'Item' not in response:
return {"statusCode": 404, "body": json.dumps({"error": "Account not found"})}
balance = response['Item']['balance']
return {"statusCode": 200, "body": json.dumps({"balance": balance})}
Configure Permissions
Ensure your Lambda function has permissions to access DynamoDB by attaching an appropriate IAM policy.
Step 5: Set Up API Gateway
Create an API Gateway Resource
- Create a REST API in API Gateway.
- Add a resource named
/get_balance
with a POST method integrated with your Lambda function.
Enable CORS for API Gateway
Enable CORS in both the POST method settings and by adding an OPTIONS method if needed.
Deploy Your API Gateway
Deploy your API to a stage (e.g., dev
) and note down its invoke URL.
Step 6: Connect Frontend to Backend
Update your JavaScript file with the API endpoint URL from API Gateway:
javascriptconst API_ENDPOINT = 'https://<API-ID>.execute-api.us-east-1.amazonaws.com/dev/get_balance';
document.getElementById('checkBalance').addEventListener('click', async () => {
const accountId = document.getElementById('accountIdForBalance').value;
const response = await fetch(API_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ accountId })
});
const result = await response.json();
document.getElementById('balanceResult').textContent = result.balance
? `Balance: $${result.balance}`
: result.error;
});
Troubleshooting Common Issues
- CORS Errors: Ensure CORS is enabled on both S3 and API Gateway.
- Access Denied Errors: Verify IAM permissions for Lambda and S3.
- Testing APIs: Use tools like Postman or cURL to test endpoints before integrating them into your frontend.
Conclusion
Deploying a web app in AWS is highly achievable with services like S3, Lambda, DynamoDB, and API Gateway working together seamlessly. By following this step-by-step guide, you can build scalable serverless applications while avoiding common deployment pitfalls like CORS issues or denied access errors.
This approach not only simplifies infrastructure management but also ensures scalability, security, and cost efficiency—making it ideal for modern web applications!
Read more such articles from our Newsletter here.