CloudPulse is an intentionally constrained, production-style cloud deployment designed to demonstrate container orchestration, Infrastructure as Code, and cost-conscious AWS architecture. The application consists of a React + TypeScript frontend, a Spring Boot REST API, and a PostgreSQL database deployed as containers on Amazon ECS using the EC2 launch type.
The system runs on a single EC2 instance with no load balancer, no NAT Gateway, and no managed database services. All infrastructure is provisioned with Terraform, and container images are built and deployed via GitHub Actions using OIDC-based role assumption.
This project emphasizes engineering tradeoffs, operational simplicity, and cost control while reflecting real-world deployment fundamentals.
- React + TypeScript (Vite)
- Built into static assets
- Served via nginx container
- SPA routing via
try_files - API calls made via relative
/apipaths
- nginx listening on port 80
/apiproxied tohttp://127.0.0.1:8080- No TLS termination
- No load balancer
- Spring Boot (Java 17)
- REST endpoints:
GET /api/healthGET /api/servicesPOST /api/services
- JPA entity:
service_instances - Hibernate
ddl-auto=update - CORS configured
- No authentication layer
- PostgreSQL 16 (containerized)
- Database:
cloudpulse - Host-mounted volume at
/opt/cloudpulse/pgdata - No RDS
- No migration tooling
- Single ECS task definition
- Three containers:
postgresbackendfrontend
networkMode = host- Backend depends on Postgres
HEALTHY - Frontend depends on Backend
START - Environment variables injected at task level
- Logs shipped to CloudWatch via
awslogsdriver
Provisioned entirely using Terraform.
- Remote state stored in S3
- State locking via DynamoDB
- Separate bootstrap and application stacks
- Amazon ECS (EC2 launch type)
- Auto Scaling Group:
min = 1max = 1desired = 1
- Instance type:
t3.micro - Capacity provider attached
- VPC with 2 public subnets
- Internet Gateway attached
- No private subnets
- No NAT Gateway
- Security Group:
- Inbound TCP 80 from
0.0.0.0/0 - Ports 8080 and 5432 not publicly exposed
- Inbound TCP 80 from
- Security boundary enforced at the instance level
GitHub Actions handles build and deployment.
On push to the main branch:
- Backend Docker image is built
- Frontend Docker image is built
- Images are pushed to Amazon ECR
- GitHub OIDC assumes an IAM role (no static AWS credentials)
- ECS service is updated to use the new images
This provides automated, repeatable deployments without storing long-lived credentials.
Browser
→ nginx (port 80)
→ Spring Boot (localhost:8080)
→ PostgreSQL (localhost:5432)
All traffic enters through port 80 on a single EC2 instance.
Container-to-container communication occurs via localhost due to host networking.
ECS on EC2 was selected to:
- Reduce monthly costs for a continuously running service
- Maintain direct control over instance sizing
- Demonstrate understanding of capacity providers and ASGs
- Avoid per-task Fargate pricing overhead
Tradeoff
- Increased operational responsibility (instance lifecycle, AMI management)
- Less abstraction than Fargate
This choice prioritizes cost transparency and infrastructure control.
An ALB was intentionally omitted to:
- Eliminate additional fixed monthly cost
- Reduce architectural complexity
- Keep traffic flow simple for a single-instance deployment
Tradeoff
- No managed health check routing
- No horizontal scaling capability
For a single-instance architecture, nginx provides sufficient reverse proxy functionality.
The deployment uses public subnets only.
Rationale
- NAT Gateways introduce significant monthly cost
- The workload does not require outbound-only private networking
- Ports 8080 and 5432 are not exposed publicly
Tradeoff
- Database is not isolated in a private subnet
- Security relies primarily on Security Groups
This reflects a deliberate cost-performance tradeoff suitable for a controlled portfolio deployment.
PostgreSQL runs as a container within the ECS task.
Rationale
- Avoid RDS baseline cost
- Keep the entire system self-contained
- Demonstrate multi-container task orchestration
Tradeoff
- No automated backups
- No managed failover
- Persistence handled via host-mounted volume
This approach emphasizes infrastructure mechanics over managed service convenience.
The system runs on one t3.micro instance.
Rationale
- Minimize infrastructure cost
- Demonstrate minimal viable production architecture
- Align resources to workload size
Tradeoff
- No redundancy
- Single point of failure
This is an intentionally constrained deployment to highlight engineering fundamentals rather than enterprise resiliency.
All infrastructure components are defined in Terraform.
Benefits
- Repeatable provisioning
- Version-controlled infrastructure
- Clear separation of bootstrap and application layers
- Remote state with locking to prevent drift and race conditions
This ensures the environment can be recreated from code without manual configuration.
GitHub Actions assumes an IAM role using OIDC.
Rationale
- No static AWS credentials stored in GitHub
- Short-lived credential model
- Modern CI/CD security practice
Tradeoff
- Slightly more complex IAM configuration
- Requires trust relationship setup
This reflects secure automation patterns expected in production environments.
- Logs available in CloudWatch
- ECS service maintains desired count of 1
- Postgres data persisted on host volume
- Service health endpoint:
/api/health - Manual scaling required (ASG max = 1)
This system is not designed for high availability or scale.
It is designed to demonstrate controlled, intentional cloud architecture decisions.
- No TLS
- No authentication
- No horizontal scaling
- No automated database backups
- No blue/green deployments
- No load balancing
These constraints are deliberate to:
- Control cost
- Reduce architectural complexity
- Focus on infrastructure fundamentals
- Multi-container ECS task orchestration
- Reverse proxy configuration with nginx
- Spring Boot container deployment
- Stateful container persistence
- Terraform-managed AWS infrastructure
- Remote state + locking
- OIDC-based CI/CD
- Cost-aware architectural tradeoffs
CloudPulse is a minimal but production-structured cloud deployment designed to demonstrate core AWS infrastructure engineering capabilities under real operational constraints.