Splitly is a group expense management and sharing platform developed to help users track shared expenses, calculate balances, and manage settlement between members in a transparent and convenient way.
The system is built using a modern web architecture with React + Vite for the user interface, Node.js/Express for the backend service, and MongoDB Atlas as the database. The infrastructure is deployed on AWS, using Amazon EC2 to run both the backend and frontend, Amazon S3 to store receipts and supporting images, Amazon CloudWatch to monitor the system, and Amazon VPC together with Security Groups to ensure secure network connectivity.
The platform provides core features such as group management, expense recording and sharing, balance calculation, payment tracking, and electronic receipt storage. The architecture is designed to be scalable and suitable for small to medium-sized user groups.
Group expense management is still mostly handled manually through spreadsheets or chat messages. As the number of members and expenses increases, tracking who has paid, who still owes money, and how much needs to be settled becomes complicated and error-prone.
Some common difficulties include:
Splitly is built on AWS to digitalize group expense management. The system provides group management, expense recording, balance calculation, payment tracking, and receipt storage in one centralized platform, while using AWS services to ensure deployment, storage, and monitoring are handled efficiently.
Deploying Splitly brings several benefits:
The project uses a monolithic application architecture for the application layer, deployed centrally on AWS cloud infrastructure with 3 main layers:
/api path to the backend running on port 5000, which is managed by PM2..env file on EC2.
Web Interface & Proxy: The frontend application (React/Vite) is built into static files and served directly by the Nginx server running on Amazon EC2. Nginx also acts as a Reverse Proxy to route API requests from users to the backend.
Business Processing (Backend): Amazon EC2, sharing the same server with the web interface, runs the backend API through Node.js/PM2 and handles authentication, group management, expenses, payments, receipts, disputes, and notifications.
Data Storage: MongoDB Atlas stores the core data including user information, groups, expenses, settlements, disputes, and notifications.
Receipt Storage: Amazon S3 (Receipts Bucket) stores receipt images and uploaded files, reducing local storage usage on EC2.
Network Connectivity: Amazon VPC, Public Subnet, Internet Gateway, and Elastic IP form the network foundation, supporting EC2 access from users, file uploads to S3, connectivity to MongoDB Atlas, and requests to external services such as VNPay and Gmail SMTP.
System Security: The Web Security Group acts as a firewall, restricting which ports and network sources can access EC2, for example allowing only port 80 for web traffic and 22 for SSH administration.
Configuration & Secret Management: Sensitive system information such as MongoDB URI, JWT Secret, Gmail credentials, and VNPay keys is stored through environment variables in the .env file directly on EC2.
Access Control: An AWS IAM Role grants least-privilege permissions to the EC2 server so it can access the S3 Receipts Bucket and CloudWatch securely without storing Access Keys on the server.
System Monitoring: Amazon CloudWatch runs in the background to collect application logs, monitor EC2 resource status such as CPU, RAM, and Disk, and create alerts when incidents are detected.
Alert Delivery: Amazon SNS acts as the delivery channel, sending email or notification messages from CloudWatch and AWS Budgets to the administrator.
Cost Management: AWS Budgets continuously tracks AWS infrastructure spending and triggers alerts when usage reaches or exceeds the configured budget threshold.
The figure below describes the upgraded architecture proposed for Splitly in the future. This architecture is not part of the current deployment scope, but it is intended as the next development stage of the system.

In the proposed architecture, the frontend application is separated from the backend server. The React/Vite frontend is built into static files and stored in an Amazon S3 Frontend Bucket. Amazon CloudFront is used to distribute the frontend content to users, reducing latency and improving page load speed.
Amazon Route 53 is used to manage the domain name and route users to the system. AWS WAF is placed in front of CloudFront to protect the application from common web attacks. AWS Certificate Manager is used to manage SSL/TLS certificates, allowing the system to provide secure HTTPS connections.
The backend application continues to be deployed on an Amazon EC2 instance in the Public Subnet of Amazon VPC. The backend is responsible for business logic, REST API services, MongoDB Atlas integration, and uploading receipt files to the Amazon S3 Receipts Bucket.
Amazon S3 Receipts Bucket is used separately to store receipt images and uploaded files. Separating the Frontend Bucket and Receipts Bucket makes data management clearer and allows appropriate access policies for each resource type.
Amazon CloudWatch is used to collect infrastructure metrics and application logs. Amazon SNS is responsible for sending operational alerts to the administrator, while AWS Budgets monitors resource spending and sends notifications when the spending level approaches or exceeds the configured budget.
AWS IAM is used to manage access permissions between EC2 and AWS services. EC2 is assigned an IAM Role so the backend can access S3 and CloudWatch without storing Access Keys and Secret Access Keys directly on the server.
Compared with the current architecture, the proposed future architecture brings the following improvements:
Frontend and backend separation: Static frontend files are moved from EC2 to Amazon S3, allowing EC2 to focus on API processing and backend business logic.
Better performance: Amazon CloudFront caches and delivers frontend content through edge locations, reducing page load time for users.
Custom domain support: Amazon Route 53 allows users to access Splitly through a domain name instead of directly using the Elastic IP address.
HTTPS support: AWS Certificate Manager manages SSL/TLS certificates, helping encrypt data transmitted between users and the system.
Improved web application security: AWS WAF helps filter and control requests before they reach CloudFront and downstream components.
Reduced EC2 load: Serving the frontend through Amazon S3 and CloudFront reduces the amount of traffic and work the EC2 server has to handle.
Clearer storage management: The Frontend Bucket is used for static interface files, while the Receipts Bucket is used separately for user-uploaded files.
Better scalability: The frontend and backend can be upgraded or scaled independently depending on system usage.
Improved monitoring: Amazon CloudWatch, Amazon SNS, and AWS Budgets help the team track system status, receive incident alerts, and control costs more effectively.
This architecture creates a foundation for future expansion of Splitly, such as adding an Application Load Balancer, Auto Scaling, Amazon Cognito, AWS Lambda, or CI/CD deployment pipelines.
Clone the source code from GitHub to the EC2 server and configure sensitive environment variables in the .env file. Install and build the frontend (React/Vite), and configure Nginx to serve static files and act as a reverse proxy. Build the backend (Node.js/Express) and keep it running with PM2; connect the backend successfully to MongoDB, the S3 Receipts Bucket, and third-party services (VNPay, Gmail). Finally, test the API, receipt upload functionality, log monitoring, and bring the system into production.
The system is deployed in the AWS Singapore Region (ap-southeast-1). The entire application (frontend and backend) is stored and operated centrally on a single Amazon EC2 instance inside the Public Subnet of a VPC.
The source code is managed on GitHub. The deployment process, including dependency installation and code building, is performed directly on the EC2 environment through the command line.
Core business data is securely stored in MongoDB Atlas. Static files such as images and receipts uploaded by users are pushed to Amazon S3 Receipts Bucket to optimize storage.
The EC2 instance communicates with the Internet through an Internet Gateway and Elastic IP. Security Groups are configured to allow port 80 (HTTP) for web traffic and port 22 (SSH) for administration. Nginx routes traffic by serving static frontend files or proxying API requests to the backend running on internal port 5000.
Sensitive information such as Database URI, JWT Secret, and integration keys is protected through environment variables stored in the .env file. The EC2 instance is assigned an IAM Role to access the S3 Receipts Bucket and CloudWatch following the principle of least privilege.
Amazon CloudWatch is configured to collect server metrics and application logs. Amazon SNS works as the notification channel and sends alerts to the administrator when the system encounters incidents or when resources become overloaded.
AWS Budgets continuously monitors the cost of the AWS ecosystem and automatically sends alerts when spending reaches or exceeds the configured budget limit.
The system is deployed in the Singapore region to optimize performance and reduce latency for users in Vietnam. The EC2-based architecture is fully suitable for a student project budget and can be scaled up in RAM or CPU if traffic increases.
The project is implemented in 4 main phases over approximately 3 months to ensure development, testing, and deployment are carried out systematically.
Develop the Frontend using React + Vite.
Develop APIs using Node.js and Express.
Integrate MongoDB Atlas.
Build the core features:
The system is designed for a small-scale learning and testing purpose, therefore the project prioritizes AWS Free Tier services and low-cost AWS services whenever possible.
Amazon EC2: $0.00/month (using a t3.micro instance under AWS Free Tier, 750 hours/month. Used to run both Nginx and the Node.js backend).
Amazon S3 Standard: $0.10/month (estimated 5 GB of storage for the Receipts Bucket, with around 2,000 PUT/GET requests).
Amazon CloudWatch: $0.03/month (pushing basic EC2 monitoring metrics and storing application logs).
Amazon SNS: $0.00/month (estimated 100 alert emails per month, fully within Free Tier).
Amazon VPC: $0.00/month (includes 1 VPC, Public Subnet, Internet Gateway, Route Table, and Security Group).
Elastic IP: $3.65/month (AWS charges $0.005/hour for public IPv4 addresses, including the Elastic IP attached to EC2).
AWS IAM: $0.00/month (managing IAM Roles and access permissions for the system).
Estimated Total Cost: About $3.78/month, equivalent to $45.36/12 months.
During development, the team plans to maximize the use of AWS Free Tier, combined with storing security-related configuration directly on the server through the .env file, in order to minimize operating costs. After the system becomes stable, the actual cost will be monitored continuously via AWS Budgets and can be recalculated using the AWS Pricing Calculator if real user traffic exceeds the initial estimate.