Introduction
This blog post showcases the AWS infrastructure written in Terraform for the backend of alumni-connect, a MVP of a college project written in FastAPI with a PostgreSQL database.
The terraform repo: https://github.com/ShobanChiddarth/alumni-connect-terraform
The backend repo: https://github.com/ShobanChiddarth/alumni-connect-backend
Architecture
VPC Design
Since this is an MVP, I went with the absolute minimal for everything. 1 VPC exists on ap-south-1. It has an internet gateway. Frontend is hosted in netlify, so API requests as well as management traffic (SSH) will enter through the internet gateway.
Subnet Design
There are 4 subnets in total.
- A public subnet to handle management traffic (
ap-south-1a) - 2 private subnets for backend and database EC2 instances (
ap-south-1a) - Another public subnet to satisfy AWS's hard requirement of multi AZ for load balancers (
ap-south-1b)
The management subnet:
- Contains the bastion EC2
- Contains a NAT gateway for EC2 instances in the private subnet to reach the internet
Load Balancer
The backend EC2 has no public IP and sits in a private subnet. Its security group only accepts port 8000 from the ALB security group - there is no direct path from the internet to the backend. The ALB is the only entry point.
- listens on port 80 for HTTP traffic from the public internet
- spans across
ap-south-1a(management subnet) andap-south-1b(empty subnet) - AWS requires an internet-facing ALB to span at least 2 AZs - forwards the traffic from the internet to port 8000 in the backend EC2
Security Groups Design
- SSH traffic from the internet is allowed only to the bastion EC2
- SSH traffic to the backend and database EC2s are allowed only from the bastion EC2
- HTTP traffic from the internet is allowed only to the load balancer
- HTTP traffic to the backend is allowed only from the load balancer
- Database traffic (port 5432) to the database EC2 is allowed only from the backend EC2
SSH Keys
- Bastion EC2's SSH private key stays on the local computer of the person deploying this
- Other EC2s SSH private key stays in the bastion
EC2 instances
- Backend EC2 is set to pull and run docker image
shobanchiddarth/alumni-connect-backend:0.0.2 - Database EC2 is set to pull and run docker image
postgres:16
NAT Gateway Cost Problem
I wrote a LinkedIn post about this. Click here to view it.
If you are not able to see it, here are the contents of the post:
I recently faced a problem with making EC2 instances communicate with the internet while deploying a FastAPI+Postgres backend architecture on AWS using Terraform. NAT Gateways exist to solve this - a NAT gateway can be placed in a public subnet and traffic can be routed through it.
But NAT Gateways are costly. ~$0.045/hr just to exist, plus data transfer charges.
The solution I used: keep the NAT gateway in the Terraform code, but destroy it immediately after deployment. Private instances lose internet access after packages are updated, Docker images are pulled, and containers are running.
terraform destroy -target=aws_nat_gateway.alumni-nat-gw -target=aws_eip.nat-gateway-elastic-ip
I also tried a NAT instance - an EC2 that acts as a router - but ran into configuration issues getting it to actually forward traffic. Ended up not going down that path for this project.
This temporary NAT gateway approach is good enough for a college project MVP with almost no users that gets destroyed in a few hours anyway.
Has anyone dealt with this in production? Is there a cleaner pattern for private subnet internet access beyond NAT gateway or NAT instance?
#Terraform #AWS #VPC #CloudComputing #IaC #CloudCost
Steps to Deploy
-
Clone the repo
git clone https://github.com/ShobanChiddarth/alumni-connect-terraform cd alumni-connect-terraform/infrastructure -
Set AWS credentials
export AWS_ACCESS_KEY_ID="..." export AWS_SECRET_ACCESS_KEY="..." -
Set the database password
export TF_VAR_db_password="..." -
Deploy
terraform init terraform apply -
Destroy the NAT gateway after apply
terraform destroy \ -target=aws_nat_gateway.alumni-nat-gw \ -target=aws_eip.nat-gateway-elastic-ip
To tear down everything:
terraform destroy
Proof of Deployment
These are screenshots I took when it was live. I then destroyed the whole infrastructure.
I archived the API landing URL (first image) in Wayback Machine. Here is the link: https://web.archive.org/web/20260322130840/http://alumni-alb-backend-83642402.ap-south-1.elb.amazonaws.com/
Conclusion
This is the full Terraform infrastructure for the alumni-connect backend.





Top comments (0)