Skip to main content

Command Palette

Search for a command to run...

Scaling to a 3-Tier Architecture on AWS with NGINX, React, Node.js & MongoDB

Updated
9 min read
Scaling to a 3-Tier Architecture on AWS with NGINX, React, Node.js & MongoDB

1. Introduction

In Phase 1, we deployed everything on a single server:

  • NGINX

  • React Frontend

  • Node.js Backend

  • MongoDB

While this setup works for learning, it is not suitable for real-world production systems.

Problems with Single Server (Phase 1)

  • Single point of failure (server crash = full downtime)

  • No scalability

  • Poor performance under load

  • Not production-ready


2. Phase 2

We move to a real-world production architecture by splitting components into multiple servers.

  • Each server has one responsibility only

  • Each service is maintained in a separate repository

Architecture Overview

Security Design (Very Important)

  • Only NGINX is exposed to the internet

  • Internal services communicate via private IPs

  • Strict firewall rules using Security Groups

Server Role Port Access
NGINX Entry point 80 Public
Frontend React App 3000 NGINX only
Backend Node API 5000 NGINX only
MongoDB Database 27017 Backend only
  • This improves security and isolation

Step 1 : Launch 4 EC2 Instances

Configuration:

  • Ubuntu 22.04
  • t2.micro
  • Same VPC

  • Same key pair

Create 4 EC2 instances:

  • nginx-server

  • frontend-server

  • backend-server

  • mongo-server

  • After launching all EC2 instances, you must configure inbound rules in Security Groups.

Step 2 : MongoDB Setup (Database Server)

1. Connect to MongoDB Server

ssh -i key.pem ubuntu@MONGO_PUBLIC_IP
  • This connects you to your database server where MongoDB will run.

2. Install MongoDB

  • This installs MongoDB on your server
# Install required tools
sudo apt update
sudo apt install -y gnupg curl

# Add MongoDB GPG key
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor

# Add MongoDB repository
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \
sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list

# Update and install MongoDB
sudo apt update 
sudo apt install -y mongodb-org

3. Start MongoDB

sudo systemctl start mongod
sudo systemctl enable mongod
  • Start MongoDB

  • Enable auto-start after reboot

4. Allow Remote Access

Edit config:

sudo vi /etc/mongod.conf

Change:

bindIp: 127.0.0.1

To:

bindIp: 0.0.0.0

What does this mean?

Value Meaning
127.0.0.1 Only local access (same server only)
0.0.0.0 Allow connections from other servers

Why we change this?

  • In our architecture: Backend server is different machine

  • MongoDB must accept external connection

  • So backend can connect like:

    mongodb://MONGO_PRIVATE_IP:27017
    

5. Restart MongoDB

sudo systemctl restart mongod

6. Verify MongoDB

sudo systemctl statusmongod

You should see:

Active: active (running)
  • NGINX does NOT talk to MongoDB

  • Only backend connects to database


Step 3 : Backend Setup (Node.js Server)

1. Install Node.js

curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
  • Installs Node.js on your backend server
  • Adds Node.js repository

  • Installs Node.js + npm

Verify Installations:

node -v
npm -v
  • Shows Node.js version

  • Shows npm version

2. Install Git

sudo apt install git -y 
  • This installs Git on your server

3. Clone Project

git clone https://github.com/Niranjan-Projects/Backend.git
cd Backend
npm install
  • git clone → copies project from GitHub
  • npm install → installs all required packages
npm install

4. Create .env File

vi .env

Add This :

MONGO_URI=mongodb://<MONGO_PRIVATE_IP>:27017/devops  
PORT=5000
JWT_SECRET=kkdevops
  • Use MongoDB PRIVATE IP only (very important)
  • MONGO_URI → connects backend to MongoDB

  • JWT_SECRET → used for login authentication

  • PORT → backend runs on port 5000

5. Start Backend node server.js

node server.js
  • Starts your backend server
  • Backend startsnode server.js runs your app

  • Connects to MongoDB → using .env connection string

  • Listens on port 5000 → ready to accept requests


Step 4 : Frontend Setup (React Server)

1. Install Git

sudo apt update
sudo apt install -y git
  • Installs Git (needed to download code)

2. Install Node.js

curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
  • Installs Node.js + npm

  • You saw warning (Node 18 deprecated) → it’s OK for now

3. Verify Installation

node -v
npm -v
  • Confirms Node.js is installed

4. Clone Frontend Project

git clone https://github.com/Niranjan-Projects/Frontend.git
cd Frontend
  • Downloads your React project

5. Install Dependencies

npm install
  • Installs all required packages

  • Warnings are normal → ignore

6. Create .env File

vi .env

Add:

REACT_APP_API_URL=/api
  • This is VERY IMPORTANT

  • What it means: Frontend will call /api NGINX will redirect it to backend

7. Install PM2

sudo npm install -g pm2
  • Process manager (runs app in background)

8. Build Frontend (IMPORTANT )

npm run build

Creates:

build/
  • Optimized production files

9. Install Serve

sudo npm install -g serve
  • Tool to run production build

10. Run Frontend (Production Mode)

pm2 start "serve -s build -l 3000" --name frontend
  • Runs app on port 3000

11. Save & Enable Auto Start

pm2 save
pm2 startup
  • Keeps app running after reboot

12. Check Status

pm2 status

Expected: Online


Important Note

Currently, you can access your application using:

http://FRONTEND_PUBLIC_IP:3000
  • This is only for testing purposes

  • In real-world production: Users should NOT access port 3000

  • Frontend should NOT be public

  • Now, we will configure NGINX to: Act as a public entry point

  • Route traffic to frontend

  • Route /api requests to backend


Step 5 : NGINX Setup (Final Integration)

In this step, we configure NGINX as the main entry point for our application.

  • Users will access only NGINX

  • NGINX will route traffic to frontend and backend

1. Install NGINX

sudo apt update
sudo apt install -y nginx
  • Installs NGINX web server

2. Create NGINX Configuration

 sudo vi /etc/nginx/sites-available/devops

Paste this configuration:

server {
    listen 80;
    server_name _;

    # Frontend (React running on port 3000)
    location / {
        proxy_pass http://<FRONTEND_PRIVATE_IP>:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # Backend (Node.js running on port 5000)
    location /api/ {
        proxy_pass http://<BACKEND_PRIVATE_IP>:5000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
  • <FRONTEND_PRIVATE_IP> → Replace with your frontend server private IP

  • <BACKEND_PRIVATE_IP> → Replace with your backend server private IP

  • / → goes to Frontend (React app)

  • /api/ → goes to Backend (Node.js API)

  • NGINX acts like a traffic manager

3. Enable Configuration

sudo ln -s /etc/nginx/sites-available/devops /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
  • Activates your new config

  • Removes default NGINX page


4. Test and Restart NGINX

sudo nginx -t
sudo systemctl restart nginx
  • Make sure config is valid before restarting

Step 6 : Access Application via NGINX

  • Now your complete setup is ready

  • Open your browser and access:

http://NGINX_PUBLIC_IP

1. Open Application

  • The frontend will load successfully

  • This is served through NGINX (port 80)

2. Register a New User

  • Click on Student Login

  • Click Create Account

  • Enter details:

  • Click Signup

  • User will be created successfully

3. Login

  • Go back to login page

  • Enter same credentials

  • Click Login

  • You will be logged in successfully.

What is happening in background?

User → NGINX → Frontend
                ↓
              /api
                ↓
            Backend
                ↓
            MongoDB
  • Frontend sends login request

  • NGINX forwards /api to backend

  • Backend validates and stores data in MongoDB

Step 6 : Connect to MongoDB & Verify Data

Now let’s check whether our application data is actually stored in MongoDB.

1. Connect to MongoDB Server

  • This connects you to your MongoDB server

2. Open MongoDB Shell

mongosh
  • This opens MongoDB CLI

3. Switch to Database

use devops
  • Now you are inside your application database

4. Check Collections

show collections

Output:

users
  • This means your app created a collection successfully

5. View User Data

db.users.find()
  • You will see data like:
  • User data stored correctly

Conclusion

In this phase, we successfully built a 3-tier architecture on AWS by separating frontend, backend, and database into different servers and using NGINX as the entry point.

This setup improves scalability, security, and reflects real-world production architecture.


Next

In the next blog, we will move forward by implementing Docker and Kubernetes to containerize and manage this application efficiently.

  • Docker → Containerizing applications

  • ☸️ Kubernetes → Orchestrating and managing containers at scale