TradAI Final Architecture - VPC & Networking¶
Version: 9.2.1 | Date: 2025-12-09
VPC Design Overview¶
CIDR Allocation¶
| VPC/Subnet | CIDR Block | Purpose | Hosts |
|---|---|---|---|
| VPC | 10.0.0.0/16 | Main VPC | 65,536 |
| Public Subnet AZ-1 | 10.0.1.0/24 | ALB, NAT Instance | 254 |
| Public Subnet AZ-2 | 10.0.2.0/24 | ALB, NAT Instance (standby) | 254 |
| Private Subnet AZ-1 | 10.0.11.0/24 | ECS Tasks, Lambda | 254 |
| Private Subnet AZ-2 | 10.0.12.0/24 | ECS Tasks, Lambda | 254 |
| Database Subnet AZ-1 | 10.0.20.0/24 | RDS Primary | 254 |
| Database Subnet AZ-2 | 10.0.21.0/24 | RDS Standby | 254 |
Network Architecture Diagram¶
┌─────────────────────────────────────────────────────────────────────────────────┐
│ VPC: 10.0.0.0/16 │
│ Region: us-east-1 │
│ │
│ ┌─────────────────────────────────────┐ ┌─────────────────────────────────────┐
│ │ AZ-1 (us-east-1a) │ │ AZ-2 (us-east-1b) │
│ │ │ │ │
│ │ ┌────────────────────────────────┐ │ │ ┌────────────────────────────────┐ │
│ │ │ PUBLIC SUBNET: 10.0.1.0/24 │ │ │ │ PUBLIC SUBNET: 10.0.2.0/24 │ │
│ │ │ │ │ │ │ │ │
│ │ │ ┌─────────────┐ ┌───────────┐ │ │ │ │ ┌─────────────┐ ┌───────────┐ │ │
│ │ │ │ ALB │ │ NAT │ │ │ │ │ │ ALB │ │ NAT │ │ │
│ │ │ │ (Target) │ │ Instance │ │ │ │ │ │ (Target) │ │ (Standby) │ │ │
│ │ │ │ │ │ t4g.nano │ │ │ │ │ │ │ │ │ │ │
│ │ │ └─────────────┘ └─────┬─────┘ │ │ │ │ └─────────────┘ └───────────┘ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ Route: 0.0.0.0/0 → IGW │ │ │ │ Route: 0.0.0.0/0 → IGW │ │
│ │ └────────────────────────┼───────┘ │ │ └────────────────────────────────┘ │
│ │ │ │ │ │
│ │ ┌────────────────────────┼───────┐ │ │ ┌────────────────────────────────┐ │
│ │ │ PRIVATE SUBNET: 10.0.11.0/24 │ │ │ │ PRIVATE SUBNET: 10.0.12.0/24 │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ ┌─────────────────────▼─────┐ │ │ │ │ ┌─────────────────────────┐ │ │
│ │ │ │ ECS Services │ │ │ │ │ │ ECS Services │ │ │
│ │ │ │ ├─ Backend API │ │ │ │ │ │ ├─ Backend API │ │ │
│ │ │ │ ├─ Data Collection │ │ │ │ │ │ ├─ Data Collection │ │ │
│ │ │ │ └─ MLflow │ │ │ │ │ │ └─ MLflow │ │ │
│ │ │ └───────────────────────────┘ │ │ │ │ └─────────────────────────┘ │ │
│ │ │ │ │ │ │ │ │
│ │ │ ┌───────────────────────────┐ │ │ │ │ ┌─────────────────────────┐ │ │
│ │ │ │ Lambda (VPC) │ │ │ │ │ │ Lambda (VPC) │ │ │
│ │ │ │ ├─ validate-strategy │ │ │ │ │ │ (Same functions) │ │ │
│ │ │ │ ├─ data-proxy │ │ │ │ │ └─────────────────────────┘ │ │
│ │ │ │ └─ others... │ │ │ │ │ │ │
│ │ │ └───────────────────────────┘ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ Route: 0.0.0.0/0 → NAT Inst. │ │ │ │ Route: 0.0.0.0/0 → NAT Inst. │ │
│ │ └─────────────────────────────────┘ │ │ └─────────────────────────────────┘ │
│ │ │ │ │
│ │ ┌─────────────────────────────────┐ │ │ ┌─────────────────────────────────┐ │
│ │ │ DATABASE SUBNET: 10.0.20.0/24 │ │ │ │ DATABASE SUBNET: 10.0.21.0/24 │ │
│ │ │ │ │ │ │ │ │
│ │ │ ┌────────────────────────────┐ │ │ │ │ ┌────────────────────────────┐ │ │
│ │ │ │ RDS PostgreSQL │ │ │ │ │ │ RDS (Standby/Future) │ │ │
│ │ │ │ (MLflow Backend) │ │ │ │ │ │ │ │ │
│ │ │ │ db.t4g.micro │ │ │ │ │ │ │ │ │
│ │ │ └────────────────────────────┘ │ │ │ │ └────────────────────────────┘ │ │
│ │ │ │ │ │ │ │ │
│ │ │ Route: No internet access │ │ │ │ Route: No internet access │ │
│ │ └─────────────────────────────────┘ │ │ └─────────────────────────────────┘ │
│ └─────────────────────────────────────┘ └─────────────────────────────────────┘
│ │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ VPC Endpoints │ │
│ │ │ │
│ │ Gateway Endpoints (FREE): │ │
│ │ ├─ com.amazonaws.us-east-1.s3 │ │
│ │ └─ com.amazonaws.us-east-1.dynamodb │ │
│ │ │ │
│ │ Interface Endpoints (Optional - use NAT instead for cost): │ │
│ │ ├─ com.amazonaws.us-east-1.ecr.api ($7/mo × 2 AZ = $14) │ │
│ │ ├─ com.amazonaws.us-east-1.ecr.dkr ($7/mo × 2 AZ = $14) │ │
│ │ └─ com.amazonaws.us-east-1.secretsmanager ($7/mo × 2 AZ = $14) │ │
│ │ │ │
│ │ RECOMMENDATION: Skip interface endpoints, use NAT Instance (saves $28/mo) │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ Internet Gateway │ │
│ │ (Attached to VPC) │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
INTERNET
Route Tables¶
Public Route Table¶
| Destination | Target | Purpose |
|---|---|---|
| 10.0.0.0/16 | local | VPC internal traffic |
| 0.0.0.0/0 | igw-xxxxx | Internet access |
Associated Subnets: 10.0.1.0/24, 10.0.2.0/24
Private Route Table (AZ-1)¶
| Destination | Target | Purpose |
|---|---|---|
| 10.0.0.0/16 | local | VPC internal traffic |
| 0.0.0.0/0 | eni-xxxxx (NAT Instance) | Internet via NAT |
| pl-xxxxx (S3) | vpce-xxxxx | S3 via endpoint |
| pl-xxxxx (DynamoDB) | vpce-xxxxx | DynamoDB via endpoint |
Associated Subnets: 10.0.11.0/24
Private Route Table (AZ-2)¶
| Destination | Target | Purpose |
|---|---|---|
| 10.0.0.0/16 | local | VPC internal traffic |
| 0.0.0.0/0 | eni-xxxxx (NAT Instance) | Internet via NAT |
| pl-xxxxx (S3) | vpce-xxxxx | S3 via endpoint |
| pl-xxxxx (DynamoDB) | vpce-xxxxx | DynamoDB via endpoint |
Associated Subnets: 10.0.12.0/24
Database Route Table¶
| Destination | Target | Purpose |
|---|---|---|
| 10.0.0.0/16 | local | VPC internal traffic only |
Associated Subnets: 10.0.20.0/24, 10.0.21.0/24
Security Groups¶
ALB Security Group (sg-alb)¶
Name: tradai-alb-sg
Description: Security group for Application Load Balancer
Inbound Rules:
- Protocol: TCP
Port: 443
Source: 0.0.0.0/0
Description: HTTPS from internet
- Protocol: TCP
Port: 80
Source: 0.0.0.0/0
Description: HTTP redirect to HTTPS
Outbound Rules:
- Protocol: TCP
Port: 8000-8002
Destination: sg-ecs
Description: To ECS services
- Protocol: TCP
Port: 5000
Destination: sg-ecs
Description: To MLflow service
ECS Security Group (sg-ecs)¶
Name: tradai-ecs-sg
Description: Security group for ECS tasks
Inbound Rules:
- Protocol: TCP
Port: 8000
Source: sg-alb
Description: Backend API from ALB
- Protocol: TCP
Port: 8002
Source: sg-alb
Description: Data Collection from ALB
- Protocol: TCP
Port: 8002
Source: sg-lambda
Description: Data Collection from Lambda
- Protocol: TCP
Port: 5000
Source: sg-alb
Description: MLflow from ALB
- Protocol: TCP
Port: 5000
Source: sg-ecs (self)
Description: MLflow from other ECS tasks
Outbound Rules:
- Protocol: TCP
Port: 443
Destination: 0.0.0.0/0
Description: HTTPS to AWS APIs (via NAT)
- Protocol: TCP
Port: 5432
Destination: sg-rds
Description: PostgreSQL to RDS
Lambda Security Group (sg-lambda)¶
Name: tradai-lambda-sg
Description: Security group for Lambda functions in VPC
Inbound Rules:
(None - Lambda initiates connections)
Outbound Rules:
- Protocol: TCP
Port: 8002
Destination: sg-ecs
Description: To Data Collection Service
- Protocol: TCP
Port: 443
Destination: 0.0.0.0/0
Description: HTTPS to AWS APIs (via NAT)
RDS Security Group (sg-rds)¶
Name: tradai-rds-sg
Description: Security group for RDS PostgreSQL
Inbound Rules:
- Protocol: TCP
Port: 5432
Source: sg-ecs
Description: PostgreSQL from ECS tasks
Outbound Rules:
(None - RDS does not initiate connections)
NAT Instance Security Group (sg-nat)¶
Name: tradai-nat-sg
Description: Security group for NAT Instance
Inbound Rules:
- Protocol: TCP
Port: 443
Source: 10.0.11.0/24
Description: HTTPS from private subnet AZ-1
- Protocol: TCP
Port: 443
Source: 10.0.12.0/24
Description: HTTPS from private subnet AZ-2
- Protocol: TCP
Port: 80
Source: 10.0.11.0/24
Description: HTTP from private subnet AZ-1
- Protocol: TCP
Port: 80
Source: 10.0.12.0/24
Description: HTTP from private subnet AZ-2
Outbound Rules:
- Protocol: TCP
Port: 443
Destination: 0.0.0.0/0
Description: HTTPS to internet
- Protocol: TCP
Port: 80
Destination: 0.0.0.0/0
Description: HTTP to internet
VPC Endpoint Security Group (sg-vpce)¶
Name: tradai-vpce-sg
Description: Security group for VPC Interface Endpoints
Inbound Rules:
- Protocol: TCP
Port: 443
Source: 10.0.0.0/16
Description: HTTPS from VPC
Outbound Rules:
- Protocol: All
Port: All
Destination: 0.0.0.0/0
Description: All outbound
Network ACLs (NACLs)¶
Public Subnet NACL¶
Name: tradai-public-nacl
Inbound Rules:
- Rule: 100
Protocol: TCP
Port: 443
Source: 0.0.0.0/0
Action: ALLOW
Description: HTTPS
- Rule: 110
Protocol: TCP
Port: 80
Source: 0.0.0.0/0
Action: ALLOW
Description: HTTP
- Rule: 120
Protocol: TCP
Port: 1024-65535
Source: 0.0.0.0/0
Action: ALLOW
Description: Ephemeral ports (return traffic)
- Rule: *
Protocol: All
Port: All
Source: 0.0.0.0/0
Action: DENY
Description: Deny all other
Outbound Rules:
- Rule: 100
Protocol: TCP
Port: 443
Destination: 0.0.0.0/0
Action: ALLOW
Description: HTTPS
- Rule: 110
Protocol: TCP
Port: 80
Destination: 0.0.0.0/0
Action: ALLOW
Description: HTTP
- Rule: 120
Protocol: TCP
Port: 8000-8002
Destination: 10.0.0.0/16
Action: ALLOW
Description: To ECS services
- Rule: 130
Protocol: TCP
Port: 5000
Destination: 10.0.0.0/16
Action: ALLOW
Description: To MLflow
- Rule: 140
Protocol: TCP
Port: 1024-65535
Destination: 0.0.0.0/0
Action: ALLOW
Description: Ephemeral ports
- Rule: *
Protocol: All
Port: All
Destination: 0.0.0.0/0
Action: DENY
Private Subnet NACL¶
Name: tradai-private-nacl
Inbound Rules:
- Rule: 100
Protocol: TCP
Port: 8000-8002
Source: 10.0.1.0/24
Action: ALLOW
Description: From ALB AZ-1
- Rule: 110
Protocol: TCP
Port: 8000-8002
Source: 10.0.2.0/24
Action: ALLOW
Description: From ALB AZ-2
- Rule: 120
Protocol: TCP
Port: 5000
Source: 10.0.0.0/16
Action: ALLOW
Description: MLflow from VPC
- Rule: 130
Protocol: TCP
Port: 1024-65535
Source: 0.0.0.0/0
Action: ALLOW
Description: Ephemeral ports (return traffic from NAT)
- Rule: *
Protocol: All
Port: All
Source: 0.0.0.0/0
Action: DENY
Outbound Rules:
- Rule: 100
Protocol: TCP
Port: 443
Destination: 0.0.0.0/0
Action: ALLOW
Description: HTTPS to internet (via NAT)
- Rule: 110
Protocol: TCP
Port: 5432
Destination: 10.0.20.0/24
Action: ALLOW
Description: PostgreSQL to RDS AZ-1
- Rule: 120
Protocol: TCP
Port: 5432
Destination: 10.0.21.0/24
Action: ALLOW
Description: PostgreSQL to RDS AZ-2
- Rule: 130
Protocol: TCP
Port: 1024-65535
Destination: 0.0.0.0/0
Action: ALLOW
Description: Ephemeral ports
- Rule: *
Protocol: All
Port: All
Destination: 0.0.0.0/0
Action: DENY
Database Subnet NACL¶
Name: tradai-database-nacl
Inbound Rules:
- Rule: 100
Protocol: TCP
Port: 5432
Source: 10.0.11.0/24
Action: ALLOW
Description: PostgreSQL from private AZ-1
- Rule: 110
Protocol: TCP
Port: 5432
Source: 10.0.12.0/24
Action: ALLOW
Description: PostgreSQL from private AZ-2
- Rule: *
Protocol: All
Port: All
Source: 0.0.0.0/0
Action: DENY
Outbound Rules:
- Rule: 100
Protocol: TCP
Port: 1024-65535
Destination: 10.0.11.0/24
Action: ALLOW
Description: Response to private AZ-1
- Rule: 110
Protocol: TCP
Port: 1024-65535
Destination: 10.0.12.0/24
Action: ALLOW
Description: Response to private AZ-2
- Rule: *
Protocol: All
Port: All
Destination: 0.0.0.0/0
Action: DENY
NAT Instance Configuration¶
Why NAT Instance over NAT Gateway?¶
| Aspect | NAT Gateway | NAT Instance |
|---|---|---|
| Cost | $64.80/mo (2 AZs) | $6.13/mo |
| Bandwidth | 45 Gbps | 5 Gbps |
| Availability | Managed HA | Self-managed |
| Maintenance | Zero | Patch OS |
| Savings | - | $58.67/mo |
NAT Instance Specification¶
Instance Type: t4g.nano
AMI: Amazon Linux 2023 (arm64)
Key Pair: tradai-nat-key
Subnet: Public (10.0.1.0/24)
Security Group: sg-nat
Source/Dest Check: DISABLED # Critical!
User Data:
#!/bin/bash
yum install iptables-services -y
systemctl enable iptables
systemctl start iptables
# Enable IP forwarding
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
# Configure NAT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -F FORWARD
service iptables save
Tags:
Name: tradai-nat-instance
Purpose: NAT for private subnets
Auto Scaling for HA¶
Auto Scaling Group:
Name: tradai-nat-asg
Min: 1
Max: 1
Desired: 1
Health Check:
Type: EC2
Grace Period: 300 seconds
Launch Template:
Instance Type: t4g.nano
AMI: ami-nat-configured
Network: Public subnet
Lifecycle Hook:
# Update route tables on launch
Lambda: update-nat-routes
Application Load Balancer¶
ALB Configuration¶
Name: tradai-alb
Scheme: internet-facing
Type: application
IP Address Type: ipv4
Subnets:
- 10.0.1.0/24 (us-east-1a)
- 10.0.2.0/24 (us-east-1b)
Security Groups:
- sg-alb
Listeners:
- Port: 443
Protocol: HTTPS
Certificate: arn:aws:acm:...:certificate/xxxxx
Default Action: Forward to target group
- Port: 80
Protocol: HTTP
Default Action: Redirect to HTTPS (301)
Access Logs:
Enabled: true
S3 Bucket: tradai-logs
Prefix: alb/
Target Groups¶
Backend API Target Group:
Name: tradai-backend-tg
Protocol: HTTP
Port: 8000
Target Type: ip
VPC: tradai-vpc
Health Check:
Path: /health
Interval: 30 seconds
Timeout: 5 seconds
Healthy Threshold: 2
Unhealthy Threshold: 3
Data Collection Target Group:
Name: tradai-data-tg
Protocol: HTTP
Port: 8002
Target Type: ip
Health Check:
Path: /health
Interval: 30 seconds
MLflow Target Group:
Name: tradai-mlflow-tg
Protocol: HTTP
Port: 5000
Target Type: ip
Health Check:
Path: /health
Interval: 30 seconds
Listener Rules¶
HTTPS Listener Rules:
- Priority: 1
Conditions:
- Path: /strategies/*
- Path: /data/*
- Path: /health
- Path: /backtest/*
Action: Forward to tradai-backend-tg
- Priority: 2
Conditions:
- Path: /mlflow/*
Action: Forward to tradai-mlflow-tg
- Priority: 100 (Default)
Action: Fixed Response (404)
VPC Endpoints¶
Gateway Endpoints (Free)¶
S3 Gateway Endpoint:
Service: com.amazonaws.us-east-1.s3
Type: Gateway
Route Tables:
- rtb-private-az1
- rtb-private-az2
Policy: Full access to tradai-* buckets
DynamoDB Gateway Endpoint:
Service: com.amazonaws.us-east-1.dynamodb
Type: Gateway
Route Tables:
- rtb-private-az1
- rtb-private-az2
Policy: Full access to tradai-* tables
Interface Endpoints (Optional)¶
Recommendation: Skip interface endpoints and use NAT Instance to save $28/month.
If needed for high-security environments:
ECR API Endpoint:
Service: com.amazonaws.us-east-1.ecr.api
Type: Interface
Subnets: Private subnets
Security Group: sg-vpce
Private DNS: Enabled
ECR DKR Endpoint:
Service: com.amazonaws.us-east-1.ecr.dkr
Type: Interface
Subnets: Private subnets
Security Group: sg-vpce
Private DNS: Enabled
Secrets Manager Endpoint:
Service: com.amazonaws.us-east-1.secretsmanager
Type: Interface
Subnets: Private subnets
Security Group: sg-vpce
Private DNS: Enabled
VPC Flow Logs¶
Flow Log Configuration:
Name: tradai-vpc-flow-logs
Resource: VPC
Traffic Type: ALL
Destination: CloudWatch Logs
Log Group: /aws/vpc/tradai-flow-logs
Retention: 7 days
IAM Role: tradai-flow-logs-role
Log Format: (default)
Filter Pattern: (optional)
# Alert on rejected traffic
[version, account_id, interface_id, srcaddr, dstaddr,
srcport, dstport, protocol, packets, bytes, start, end,
action="REJECT", log_status]
DNS Configuration¶
Private Hosted Zone¶
Hosted Zone:
Name: tradai.local
Type: Private
VPC: tradai-vpc
Records:
- Name: backend.tradai.local
Type: A
Alias: ALB DNS name
- Name: data.tradai.local
Type: A
Alias: ALB DNS name
- Name: mlflow.tradai.local
Type: A
Alias: ALB DNS name
- Name: db.tradai.local
Type: CNAME
Value: RDS endpoint
Cost Summary¶
| Component | Configuration | Monthly Cost |
|---|---|---|
| NAT Instance | t4g.nano | $6.13 |
| ALB | 1 LB, minimal traffic | $17.00 |
| S3 Gateway Endpoint | Free | $0.00 |
| DynamoDB Gateway Endpoint | Free | $0.00 |
| VPC Flow Logs | 7 days retention | $2.00 |
| TOTAL | $25.13 |
Savings vs NAT Gateway: $58.67/month (90% reduction)
Network Validation Checklist¶
- [x] VPC created with 10.0.0.0/16 CIDR
- [x] 6 subnets across 2 AZs (public, private, database)
- [x] Internet Gateway attached
- [x] NAT Instance in public subnet
- [x] Route tables configured correctly
- [x] Security groups with least privilege
- [x] NACLs for defense in depth
- [x] Database subnets isolated (no internet)
- [x] VPC Flow Logs enabled
- [x] Gateway endpoints for S3 and DynamoDB
- [x] ALB in public subnets
- [x] ECS tasks in private subnets
- [x] RDS in database subnets
Next Steps¶
- Review 04-SECURITY.md for security controls
- Review 09-PULUMI-CODE.md for implementation