DEV Community

Cover image for A Practical Guide to Deploying Scalable Serverless Apps on AWS
Md. Ishraque Bin Shafique
Md. Ishraque Bin Shafique

Posted on

A Practical Guide to Deploying Scalable Serverless Apps on AWS

System Diagram

Building a fully serverless application on AWS can feel overwhelming at first, but this hands-on project made the entire process clear, practical, and surprisingly enjoyable. In this guide, I walk through how I built HealthHub, a cloud-native healthcare appointment system powered by AWS Lambda, API Gateway, DynamoDB, Cognito, and a Vite-based frontend. From creating the VPC and EC2 workstation to deploying backend services with the Serverless Framework and finally launching the frontend app, this article documents every step — so you can follow along and build your own production-ready serverless project.


Step 1: Creating A VPC
Create a VPC (healthhub-vpc) in N. Virgina (us-east-1) region. The VPC should have a public subnet with an 'Internet GateWay (IGW)' for public access of the Workstation EC2 instance to be created next.

HealthHub VPC

Step 2: Create An EC2 Instance WorkStation
Create an ec2 instance with the following attributes:

  • Instance Type: t2.medium
  • VPC: healthhub-vpc
  • Subnet: public
  • Assign Public IPV4 Address: True
  • Ingress Ports Allowed:
    • 22 (tcp, ssh)
    • 5173 (tcp, app port)

t2.medium EC2 Instance

Step 3: Create IAM Role For EC2 Instance
Create an IAM Role with the name hh-role. The role should be given AdministratorAccess.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Custom IAM Role for EC2 instance

Step 4: Attach IAM Role to EC2 Instance
Attach the IAM Role hh-role with the EC2 Instance healthhub-workstation so that the instance can call out to all AWS services.

Attach IAM Role To EC2 Instance

Step 5: Setting Up The WorkStation
Log in to the healthhub-workstation EC2 instance. And then check that the required packages are installed or not.

[ec2-user@ip-10-0-4-216 ~]$ aws --version
aws-cli/2.30.4 Python/3.9.24 Linux/6.1.158-178.288.amzn2023.x86_64 source/x86_64.amzn.2023
[ec2-user@ip-10-0-4-216 ~]$ node -v
-bash: node: command not found
[ec2-user@ip-10-0-4-216 ~]$ npm -v
-bash: npm: command not found
[ec2-user@ip-10-0-4-216 ~]$ serverless --version
-bash: serverless: command not found
Enter fullscreen mode Exit fullscreen mode

Install the following dependencies:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install --lts
node -v
npm -v
npm install -g serverless@3
serverless --version
Enter fullscreen mode Exit fullscreen mode

Here is the expected output:

[ec2-user@ip-10-0-4-216 ~]$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 16555  100 16555    0     0   758k      0 --:--:-- --:--:-- --:--:--  808k
=> Downloading nvm as script to '/home/ec2-user/.nvm'

=> Appending nvm source string to /home/ec2-user/.bashrc
=> Appending bash_completion source string to /home/ec2-user/.bashrc
=> Close and reopen your terminal to start using nvm or run the following to use it now:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

[ec2-user@ip-10-0-4-216 ~]$ source ~/.bashrc

[ec2-user@ip-10-0-4-216 ~]$ nvm install --lts
Installing latest LTS version.
Downloading and installing node v24.11.1...
Downloading https://nodejs.org/dist/v24.11.1/node-v24.11.1-linux-x64.tar.xz...
######################################################################################################################################################################## 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v24.11.1 (npm v11.6.2)
Creating default alias: default -> lts/* (-> v24.11.1)

[ec2-user@ip-10-0-4-216 ~]$ node -v
v24.11.1

[ec2-user@ip-10-0-4-216 ~]$ npm -v
11.6.2

[ec2-user@ip-10-0-4-216 ~]$ npm install -g serverless@3
npm warn deprecated lodash.get@4.4.2: This package is deprecated. Use the optional chaining (?.) operator instead.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm warn deprecated querystring@0.2.1: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm warn deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm warn deprecated superagent@7.1.6: Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net

added 619 packages in 37s

134 packages are looking for funding
  run `npm fund` for details
npm notice
npm notice New patch version of npm available! 11.6.2 -> 11.6.4
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.6.4
npm notice To update run: npm install -g npm@11.6.4
npm notice

[ec2-user@ip-10-0-4-216 ~]$ serverless --version
Framework Core: 3.40.0
Plugin: 7.2.3
SDK: 4.5.1
Enter fullscreen mode Exit fullscreen mode

Step 6: Implementing The Application BackEnd

Download and install the HealthHub application backend and its dependencies with the following commands:

wget https://tcb-bootcamps.s3.us-east-1.amazonaws.com/aicloud-bootcamp/v1/module3/healthhub-module-3.zip
unzip healthhub-module-3.zip

cd healthhub-module-3/health-hub-backend/
npm install

for service in src/services/*; do (cd "$service" && npm install) done
Enter fullscreen mode Exit fullscreen mode

To deploy the resources into AWS, run the following command:

npm run deploy
Enter fullscreen mode Exit fullscreen mode

This will take a few minutes to deploy. Once deployed, go to AWS Console and check the stacks in CloudFormation.

CloudFormation Stacks

Also check the following services:

  • Cognito User Pools
  • API Gateway Endpoints
  • DynamoDB Tables
  • Lambda Functions
  • CloudWatch Logs

Step 7: Implementing The Application FrontEnd

Go to the health-hub-frontend directory and run the following command to install the necessary dependencies:

cd ../health-hub-frontend
npm install
Enter fullscreen mode Exit fullscreen mode

Copy the .env.example file to .env and put the value of VITE_API_BASE_URL.

cp .env.example .env
nano .env
Enter fullscreen mode Exit fullscreen mode

The URL can be found in API Gateway in the AWS Console.

API Gateway

Step 8: Run The Application
After setting up the API Key, run the application using the following command:

[ec2-user@ip-10-0-4-216 health-hub-frontend]$ npm run dev -- --host

> health-hub@0.0.0 dev
> vite --host


  VITE v5.3.5  ready in 249 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: http://10.0.4.216:5173/
  ➜  press h + enter to show help
Enter fullscreen mode Exit fullscreen mode

Access the Health-Hub web application using your browser, enter the following IP address:

<Your-IP-Address>:5173
Enter fullscreen mode Exit fullscreen mode

Health-Hub App

Then create two tests account, one for the doctor and one for the patient.

Doctor Account Landing Page:
Doctor Dashboard

Patient Account Landing Page:
Patient Dashboard

Log in as a patient and then book an appointment. Sign out and then log back in as a doctor to confirm that the appointment is properly booked.

Step 9: Cleaning Up Everything
Once done checking out the application and the related AWS Services that are running for the application, clean up using the following command:

cd health-hub-backend
sls remove
Enter fullscreen mode Exit fullscreen mode
[ec2-user@ip-10-0-4-216 healthhub-module-3]$ cd health-hub-backend/
[ec2-user@ip-10-0-4-216 health-hub-backend]$ sls remove
Running "serverless" from node_modules

Removing stage dev

    ✔  user-service › removed › 12s
    ✔  appointment-service › removed › 37s
    ✔  doctor-service › removed › 32s
    ✔  patient-service › removed › 32s
[ec2-user@ip-10-0-4-216 health-hub-backend]$
Enter fullscreen mode Exit fullscreen mode

The services might take a few minutes to get removed from AWS Console.

PS. Remember to delete the EC2 instance manually, otherwise it will charge extra cost.

✅ My Final Thoughts

This project taught me how to:

  • Use Serverless Framework to orchestrate AWS resources
  • Deploy a serverless backend (Lambda, DynamoDB, API Gateway)
  • Build a Vite frontend hosted on S3
  • Secure everything with Cognito
  • Monitor with CloudWatch

Top comments (0)