Ah, serverless computing - the buzzword that's been taking the tech world by storm. But what exactly is it, and why should you care? Simply put, serverless computing allows you to build and run applications without worrying about provisioning or managing servers. It's like having an army of invisible servers at your beck and call, ready to handle your application's logic whenever it's needed.
One of the coolest use cases for serverless technology is building web applications. Imagine a world where you can create a website without having to worry about scaling, patching, or maintaining servers. Sounds too good to be true, right? Well, buckle up, because that's exactly what we're going to do in this article.
Serverless is a cloud computing execution model where the cloud provider dynamically manages the allocation and provisioning of servers. With serverless, you don't have to worry about provisioning, scaling, or managing servers yourself. Instead, you deploy your code, and the cloud provider handles the server management and execution for you.
In a serverless architecture, your application's code runs in stateless compute containers that are event-triggered, ephemeral (they only run when needed and shut down automatically after use), and fully managed by the cloud provider. These containers, called "functions" in the serverless world, are typically triggered by events such as HTTP requests, database events, queue services, monitoring alerts, or other custom triggers.
The key characteristics of serverless computing include:
No Server Management: You don't have to provision, scale, or manage any servers. The cloud provider handles all the infrastructure management for you.
Event-Driven: Functions are triggered by specific events or requests, rather than running continuously.
Automatic Scaling: The cloud provider automatically allocates the necessary resources to handle the incoming workload, scaling out seamlessly as needed.
Pay-per-Use Billing: You only pay for the compute time your functions consume when they are running, plus any other cloud services used. This can result in significant cost savings compared to maintaining always-on servers.
High Availability and Fault Tolerance: Cloud providers ensure high availability and fault tolerance for serverless functions across multiple availability zones.
Popular serverless compute services include AWS Lambda, Google Cloud Functions, Azure Functions, and IBM Cloud Functions. These services allow you to deploy and run your code without provisioning or managing servers, enabling you to focus on writing application logic instead of infrastructure management.
Serverless architectures are well-suited for various workloads, including web applications, APIs, data processing, IoT backends, and more. They can help reduce operational overhead, increase scalability, and potentially lower costs for certain types of applications.
Setting the Stage
Before we dive into the code, let's set up our development environment. You'll need an AWS account and the AWS CLI installed on your machine. We'll also be using Node.js and the Serverless Framework, a popular open-source tool that makes building and deploying serverless applications a breeze.
First, install the Serverless Framework globally:
npm install -g serverless
Next, create a new directory for your project and navigate to it:
mkdir serverless-web-app
cd serverless-web-app
Initialize a new Serverless project:
serverless create --template aws-nodejs --path my-service
This will create a new directory my-service
with a basic Lambda function and other boilerplate files.
Building the Web Application
Our serverless web application will consist of two main components: a static website hosted on AWS S3, and a Lambda function to handle server-side logic. Let's start with the static website.
Create a new directory called website
in your project's root directory, and add an index.html
file with some basic HTML:
<!-- website/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Serverless Web App</title>
</head>
<body>
<h1>Welcome to my Serverless Web App!</h1>
<p>This is a static website hosted on AWS S3.</p>
</body>
</html>
Now, let's configure our Serverless project to deploy this website to an S3 bucket. Open serverless.yml
and add the following resources:
# serverless.yml
service: serverless-web-app
provider:
name: aws
runtime: nodejs18.x
resources:
Resources:
WebsiteBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:service}-${opt:stage, self:provider.stage}
WebsiteConfiguration:
IndexDocument: index.html
# ... (existing Lambda function configuration)
This will create an S3 bucket with the name serverless-web-app-[stage]
, where [stage]
is the deployment stage (e.g., dev
, prod
). The bucket will be configured to serve the index.html
file as the website index.
To deploy the website, run:
serverless deploy
This will create the S3 bucket and upload the index.html
file. The CLI output will include the website URL, which you can visit in your browser to see the static website.
Adding Server-Side Logic with Lambda
Now that we have our static website set up, let's add some server-side logic using AWS Lambda. We'll build a simple "contact form" functionality, where users can submit their name and email, and we'll save the data to a DynamoDB table.
First, we need to create the DynamoDB table. Add the following resource to serverless.yml
:
# serverless.yml
resources:
Resources:
# ... (existing resources)
ContactsTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service}-contacts-${opt:stage, self:provider.stage}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
This will create a DynamoDB table called serverless-web-app-contacts-[stage]
with a hash key id
.
Next, let's create the Lambda function that will handle the contact form submissions. In the my-service
directory, create a new file called handler.js
with the following code:
// handler.js
import AWS from 'aws-sdk';
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const TABLE_NAME = process.env.CONTACTS_TABLE;
export const handler = async (event) => {
const { name, email } = JSON.parse(event.body);
const params = {
TableName: TABLE_NAME,
Item: {
id: `contact-${Date.now()}`,
name,
email,
},
};
try {
await dynamoDb.put(params).promise();
return {
statusCode: 200,
body: JSON.stringify({ message: 'Contact form submitted successfully' }),
};
} catch (err) {
console.error(err);
return {
statusCode: 500,
body: JSON.stringify({ message: 'Error submitting contact form' }),
};
}
};
This Lambda function expects a JSON payload with name
and email
properties in the event body. It generates a unique ID for the contact, and stores the contact data in the DynamoDB table.
Finally, we need to configure the Lambda function in serverless.yml
:
# serverless.yml
functions:
app:
handler: handler.handler
events:
- http:
path: submit-contact
method: post
cors: true
environment:
CONTACTS_TABLE: ${self:service}-contacts-${opt:stage, self:provider.stage}
This sets up an HTTP endpoint (/submit-contact
) that will trigger the Lambda function when a POST request is made. The function will have access to the DynamoDB table name through the CONTACTS_TABLE
environment variable.
To deploy the Lambda function and DynamoDB table, run:
serverless deploy
The complete severless.yml
file looks like this:
service: serverless-web-app
provider:
name: aws
runtime: nodejs18.x
resources:
Resources:
WebsiteBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:service}-${opt:stage, self:provider.stage}
WebsiteConfiguration:
IndexDocument: index.html
ContactsTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service}-contacts-${opt:stage, self:provider.stage}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
functions:
app:
handler: handler.handler
events:
- http:
path: submit-contact
method: post
cors: true
environment:
CONTACTS_TABLE: ${self:service}-contacts-${opt:stage, self:provider.stage}
Connecting the Frontend
With the backend logic in place, let's update the frontend to allow users to submit the contact form. Open website/index.html
and add a form:
<!-- website/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Serverless Web App</title>
</head>
<body>
<h1>Welcome to my Serverless Web App!</h1>
<p>This is a static website hosted on AWS S3.</p>
<h2>Contact Us</h2>
<form id="contact-form">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required />
<br />
<label for="email">Email:</label>
<input type="email" id="email" name="email" required />
<br />
<button type="submit">Submit</button>
</form>
<script>
const form = document.getElementById('contact-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
const response = await fetch('/submit-contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, email }),
});
const data = await response.json();
alert(data.message);
form.reset();
});
</script>
</body>
</html>
This adds a simple contact form to the HTML, and includes a JavaScript script that sends a POST request to the /submit-contact
endpoint (which is the Lambda function we deployed earlier) when the form is submitted.
To deploy the updated website, run:
serverless client deploy
This will upload the index.html
file to the S3 bucket again.
Now, if you visit the website URL and submit the contact form, you should see a success message. You can also check the DynamoDB table in the AWS console to see the submitted contact data.
Wrapping Up
And there you have it, folks! We've built a serverless web application using AWS Lambda, S3, and DynamoDB. We've covered setting up the development environment, deploying a static website, creating a Lambda function for server-side logic, and connecting the frontend to the backend.
Serverless architectures offer numerous benefits, including scalability, cost-efficiency, and reduced operational overhead. By leveraging services like AWS Lambda, you can focus on writing code and building features, without worrying about server management. It's like having a team of hardworking elves handling the tedious infrastructure tasks for you.
Of course, this is just a simple example, and real-world serverless applications can become much more complex. But hey, we all have to start somewhere, right? The principles and services demonstrated in this article provide a solid foundation for building more advanced serverless web applications.
So, what are you waiting for? Embrace the serverless revolution and start building your next big idea today!
Top comments (12)
“and a Lambda function to handle server-side logic”. You mean the serverless-side logic? Oh wait. It’s all cool, hyped and fancy but really you’re just using someone else’s server instead of your own, which has been the case with shared hosting since, well, Geocities.
Serverless architecture abstracts away server management, allowing developers to focus solely on writing code without worrying about infrastructure. While it utilizes cloud servers, the emphasis is on the "serverless" model, where developers only pay for what they use and scale effortlessly. It does not mean that there is no servers.
You didn't get the sarcasm but that's not a reason to ask ChatGPT what serverless really means and paste it here.
LOL. No AI assistance needed for this one. That comment was all human-crafted.
Sure, if that makes you feel better about using it to write the article…
Dear Thibaut, for the past five years, I've been crafting articles across various websites. If you're unsure about how to write an article, that's perfectly fine – learning is always an option. However, if you suspect this article was generated by AI, feel free to run it through an AI detector and you will know why you need to grow your mindset.
Dude, one year ago you couldn't write a 2 sentences comment without 3 grammar errors and now you're the prodigal son of articles? Give us a break. I don't need an AI detector to do that, my integrated bullshit detector (aka common sense) already went through the roof. i.e. you're telling us the same person wrote dev.to/ritikbanger/how-to-write-gi... and this article? It's insulting to think we're stupid enough to believe so. Bye now.
AWS service is not backed by servers ?
How evil it is to call this serverless.
Although AWS services are indeed powered by servers, the term "serverless" in this context means developers can build and deploy applications without managing server infrastructure directly. It's a convenience term emphasizing the abstraction of server management tasks, enabling a more streamlined development process.
Good read. One question I have - what kind of URL is outputted when we deploy the S3 bucket? Is it a “s3.website”-type url, or a special serverless url? The reason I ask is I’m confused how we are able to submit the form to ‘/submit-contact’ and don’t have to use a fully qualified domain or lambda function URL. Thanks for the article
When you deploy the S3 bucket for your serverless web application, the URL typically takes the form of "bucket-name.s3-website-region.amazonaws.com." This is known as a "static website hosting" URL, specific to S3 hosting.
Regarding submitting the form to '/submit-contact' without using a fully qualified domain or Lambda function URL, in a typical serverless setup with AWS, you would likely employ API Gateway to create a custom RESTful API endpoint like '/submit-contact'. This API Gateway endpoint would be configured to trigger your Lambda function directly. So, although the endpoint appears to be relative, behind the scenes, API Gateway is handling the routing to the appropriate Lambda function.
In the current scenerio, you can see that we have created this endpoint.
Serverless is just a joke.
Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more