Building A Serverless Application On AWS
Uriel Bitton
AWS Cloud Engineer | The DynamoDB guy | AWS Certified | I help you supercharge your DynamoDB database ????
?? Hello there! Welcome to The Serverless Spotlight! I'm Uriel Bitton, a solutions architect on AWS and I'm here to teach you everything I know about serverless computing and optimizing for costs on the cloud.
I have built and architected over 15 serverless web applications with 12 years of experience in software development and cloud technologies.
In this edition, I'll take you through an exciting hands-on of how to easily build a fully serverless web application with the AWS cloud.
It's going to be really interesting, so let's dive right it!
Back in the day, launching an application required massive efforts from your IT infrastructure.
You had to have your servers in your data center, keep them always on, and hire experts to maintain and fix them regularly.
This would often become quite costly and require many experienced professionals with various skills to be able to host, launch, and deploy enterprise-level software.
Fast forward some years to today and performing the same process requires less than 1/4 of that previous effort.
With the cloud, one person can realistically host, maintain, and deploy that same enterprise-level software with costs near zero.
The AWS Cloud
By using the AWS cloud, we can make use of its rich ecosystem of cloud services to accomplish our business objectives in the most cost-efficient and personnel-efficient manner possible.
Serverless Services
Furthermore, AWS provides many serverless services that we can make use of to launch our business applications.
With a serverless infrastructure, we can eliminate the need to maintain servers and complex configurations.
Our compute, database and backend can all be run on servers abstracted away and maintained by AWS — the definition of serverless — allowing us to focus only on the business logic of our application.
Designing A Serverless Infrastructure For Our Application
Let’s take a look at implementing a serverless architecture for our web application, focusing on speed, simplicity, management-less processes, and near-zero costs.
Here’s a breakdown of the services and resources we’ll make use of for our purely serverless architecture.
The plan is to create the functions' code to run our server code using Lambda, storing persistent data to DynamoDB with these functions, exposing endpoints for our frontend requests with API Gateway, and hosting the application itself and its static data on S3.
Lambda
We’ll start with creating our Lambda functions that will execute the code we need on the cloud.
We’ll integrate each function with an API Gateway endpoint later on.
In the Lambda console, you can create a new function.
Click the Create function button on top.
On the create function page add a function name, your desired runtime (I’m using Node JS 16), and the necessary permissions for your function to write to DynamoDB.
On the function page scroll down to the Code section and add the following code.
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();
exports.handler = async (event) => {
try {
// Extract table name and item data from the event
const itemData = event;
// DynamoDB parameters for the put operation
const params = {
TableName: "OnlineShop",
Item: itemData,
};
// Perform the put operation to add the new item
await dynamodb.put(params).promise();
return {
statusCode: 200,
body: JSON.stringify('Item added successfully'),
};
} catch (error) {
console.error('Error adding item:', error);
return {
statusCode: 500,
body: JSON.stringify({error}),
};
}
};
The code above makes a connection with DynamoDB and accepts an input object event.
We declare a params object with the DynamoDB table name and the item that comes from the event object.
We then add that item data to our table with the dynamodb.put() method and finally return an “ok” status code and a message saying the item was successfully added to our dynamoDB table.
We can hit the Deploy button at the top to deploy our function so we can use it.
That’s it for the compute step.
API Gateway
To be able to expose this function code so we can call it on our client-side application, we must integrate our newly created Lambda function with a rest API — or in our case API Gateway.
API Gateway will expose API endpoint URLs with routes we define — such as “/add-item” or “/delete-item” — and connect them with our Lambda functions so that we can call the Lambda function code by making a fetch request to one of these endpoint URLs from our client-side application.
Let’s create a rest API by heading over to the API Gateway console in AWS.
Click the Create API button at the top and choose Rest API on the next page. Click the build button to start building a rest API.
You’ll then see the following page.
Select New API and give it a name. I’ll call it onlineshop-api to match the DynamoDB table we will create later on.
We’ll leave the default option in the API endpoint type set to Regional, and proceed to create the API by clicking on the button below.
You will be redirected to the API page.
The first thing we need to create is a resource. Let’s click the Create resource button at the top left.
A resource is a URL to expose to our client-side application with which we can make a fetch request.
Let’s define a path at “/” with the resource name “add-item” to denote that this path will be used to add an item to our database.
Check the CORS checkbox to enable CORS protection and then create the resource.
On this new page, we’ll create a new method for this path — specifically a POST method to be able to send data to our API — by clicking the Create method button in the Methods section.
You’ll be redirected to the Create Method page.
Select POST as the method type and Lambda function as the integration type (selected by default).
Scrolling down, you will see Lambda function with an input to select an existing Lambda function. Choose the Lambda function we created earlier.
You can leave the rest of the defaults and create the method.
You’ll be redirected back to the API page.
On this page, first, click the “/add-item” route so it is highlighted, and then click on the Enable CORS button.
On this page, we will select the POST checkbox only and leave the other inputs as they are and click Save.
The last step is to deploy the API.
We can click on the orange Deploy button to deploy our API.
领英推荐
Select New Stage, and add a stage name. I’ll name it “V1”.
You’ll then be redirected to a new page with your newly created stage. Here you’ll find an Invoke URL.
Copy this for later as this is the API endpoint we will use to make all our fetch requests for our client-side app to communicate with our API.
That’s all for this part.
DynamoDB
In the DynamoDB console, we’ll start by creating a new table.
We’ll add a table name “OnlineShop” — exactly as we named it in our Lambda function code above.
We’ll then select the partition and sort keys. Let’s provide itemId for the partition key and dateCreated for the sort key (leave both item types as strings).
You can leave the rest of the defaults as they are and Create the table.
Now we’ll click on the table we just created to view its details and we can then click on Explore table items to view the items in our table.
We’ll leave this page open to get back to it when we have added items to it.
Running Our Serverless App
We can now set up and run a development environment on the client side — in other words, our frontend web application.
I’ll leave the UI and business logic to you but let’s create a createItem() function which will contain our fetch call which will communicate with our API Gateway rest API, call our Lambda function which in turn will write items to our DynamoDB database.
Copy the API endpoint URL that you set aside from our deployed API in the previous section, we’ll be using it in the following code.
const createItem = async () => {
const item = {
itemId: 'product-101',
dateCreated: '2024-04-21',
name: "Apple Airpods Pro 2",
sku: "#GSBHF834BFB2B2SF",
PRICE: 350
};
try {
const res = await fetch('https://APIGATEWAYURLENDPOINT.com/add-item/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(item)
})
const data = await res.json();
console.log('Item successfully written to endpoint:', data);
}
catch(error) {
console.error('Error writing item to endpoint:', error);
}
}
The fetch URL should be replaced with the one generated by your API in API Gateway and add “/add-item” path to it.
That’s all we need to do for the front-end code.
Now all you need to do is build your app (if using a JS framework/library like React or Vue) or if you’re using plain old HTML and JS, we’ll copy those build files into S3 in the next and final section to host our web application.
S3
In the S3 console, we’ll start by creating a bucket for our web application.
Give your bucket a name and choose General purpose for the bucket type.
In the Object ownership section leave ACLs disabled option checked.
In the Block Public Access settings for this bucket section, uncheck the Block all public access checkbox.
You can leave the rest of the sections as they are and create the bucket.
You will be redirected to the buckets list page. Click on the bucket you just created.
On this page, you will be able to upload your project’s build files.
Click the orange Upload button and upload your files there.
Once you upload your build files you can close the upload page.
You can return to the bucket page.
On this page click the permissions tab at the top then click the edit button on the Bucket policy section.
In the bucket policy textarea, add the following JSON:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::uriel-onlineshop-v1/*"
}
]
}
Click on Save changes to add the policy. This policy will allow public users to access (read) your web application on the internet.
You can now click on the Properties tab and scroll all the way down to the last section.
Under static website hosting click the edit button.
On this page click the enable option to enable static website hosting.
This will allow us to host our web application on our S3 bucket. As soon we enable static website hosting, S3 will provide us with a URL with which we can use to connect our hosted web application.
Leave the inputs at their defaults and enter an entry point file for your app in the Index document input.
The entry point file is usually index.html in a classic HTML & JS app or in a build output of a React JS app.
Whatever your project’s entry point to your web app is, enter the file’s filename in the input — the one you uploaded earlier in the bucket files. I chose index.html as I am using a classic HTML website.
Save changes when you are done. You will be redirected to the properties page of your bucket. Simply scroll back down to the static website hosting section and there should be a URL there this time.
Clicking on that will display your web app.
You can now run the createItem() function within your application and verify if the item has been added to your DynamoDB table.
If it is successfully added, congrats you’ve just launched a fully serverless web application in record time and without spending a dime.
If it didn’t work, you can view the Lambda logs in AWS CloudWatch. If you need help with this read my article here.
Conclusion
Launching a serverless web application using AWS services is straightforward, quick, and cost-efficient.
In this article we went through doing just that by using Lambda serverless functions as our compute code, DynamoDB as our serverless database, API Gateway to create a rest API, and S3 to host our web application at virtually no cost at all.
By integrating all of these serverless cloud services we were able to build and launch our web applications quickly and with ease.
?? My name is Uriel Bitton and I hope you learned something of value in this edition of The Serverless Spotlight.
?? Please consider sharing it with your network to help others learn as well.
?? You can also explore my social media links here:
?? *my blog website is coming soon, so stay tuned for that.
?? I hope to see you in the next week's edition!
Uriel