Database Integration with AWS RDS (VPC Peering)

Introduction
Most production apps need a database. In this part, you'll deploy AWS RDS (PostgreSQL) in a private subnet and connect it to your ECS Fargate containers—securely, with VPC peering and security groups.
What You'll Learn:
✅ Create RDS PostgreSQL instance in private subnet
✅ Configure security groups (ECS → RDS access)
✅ Set up database credentials (AWS Secrets Manager)
✅ Connect app to RDS from ECS Fargate
✅ Database backup and auto-scaling
✅ VPC Peering for multi-VPC access
Prerequisites:
Part 5 completed (ECS Fargate with monitoring)
App with database connection code
1. Create RDS PostgreSQL Instance
Terraform Code:
# rds.tf
resource "aws_db_subnet_group" "private" {
name = "ecs-rds-subnet-group"
subnet_ids = [aws_subnet.private.id]
tags = {
Name = "rds-subnet-group"
}
}
resource "aws_security_group" "rds" {
name = "ecs-rds-sg"
vpc_id = aws_vpc.main.id
description = "Allow ECS to connect to RDS"
ingress {
description = "From ECS"
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.ecs.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "rds-security-group"
}
}
resource "aws_db_instance" "postgres" {
identifier = "ecs-postgres-db"
# Engine
engine = "postgres"
engine_version = "15.4"
instance_class = "db.t3.micro" # Free tier eligible
# Database credentials (use Secrets Manager in production)
username = "admin"
password = var.db_password # Pass via terraform.tfvars
port = 5432
# Storage
allocated_storage = 20
storage_type = "gp2"
storage_encrypted = true
delete_protection = true # Prevent accidental deletion
# Network
db_subnet_group_name = aws_db_subnet_group.private.name
vpc_security_group_ids = [aws_security_group.rds.id]
publicly_accessible = false # Private only
# Backup
backup_retention_period = 7
backup_window = "03:00-04:00"
auto_minor_version_upgrade = true
# Monitoring
monitoring_interval = 30
monitoring_role_arn = aws_iam_role.rds_monitoring.arn
tags = {
Name = "ecs-postgres"
Environment = "production"
}
}
# Output endpoint
output "rds_endpoint" {
value = aws_db_instance.postgres.endpoint
description = "RDS endpoint to connect from ECS"
}
Free Tier: db.t3.micro is free for 12 months (750 hours/month).
Expected Cost:
After free tier: ~$15/month (db.t3.micro)
Storage: $0.10/GB/month
2. Store Credentials in AWS Secrets Manager
Never hardcode passwords in code!
# secrets.tf
resource "aws_secretsmanager_secret" "db_credentials" {
name = "ecs-production/db-credentials"
tags = {
Name = "db-credentials-secret"
}
}
resource "aws_secretsmanager_secret_version" "db_credentials" {
secret_id = aws_secretsmanager_secret.db_credentials.id
secret_string = jsonencode({
username = "admin"
password = var.db_password
host = aws_db_instance.postgres.endpoint
port = 5432
dbname = "appdb"
})
}
# Grant ECS access to secret
resource "aws_iam_role_policy_attachment" "ecs_task_secrets" {
role = aws_iam_role.ecs_task_role.name
policy_arn = "arn:aws:iam::aws:policy/SecretsManagerReadWrite"
}
Access Secret in Your App (Node.js):
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager({ region: 'ap-south-1' });
async function getDBCredentials() {
const secret = await secretsManager
.getSecretValue({ SecretId: 'ecs-production/db-credentials' })
.promise();
return JSON.parse(secret.SecretString);
}
// Usage
const creds = await getDBCredentials();
const { Pool } = require('pg');
const pool = new Pool({
user: creds.username,
host: creds.host,
database: 'appdb',
password: creds.password,
port: creds.port,
});
3. Update Task Definition with Database Environment
resource "aws_ecs_task_definition" "app" {
# ... (previous config)
container_definitions = jsonencode([
{
name = "ecs-app"
image = "${aws_ecr_repository.app.repository_url}:v1"
# Environment variables (reference Secret ARN)
secrets = [
{
name = "DB_HOST"
valueFrom = aws_secretsmanager_secret.db_credentials.arn
}
]
# Or pass RDS endpoint directly
environment = [
{
name = "DB_PORT"
value = "5432"
},
{
name = "DB_NAME"
value = "appdb"
}
]
}
])
}
4. Test Database Connection
From ECS Container:
# Exec into container
aws ecs execute-command \
--cluster ecs-production-cluster \
--service ecs-app-service \
--interactive \
--command "/bin/sh"
# Inside container:
psql postgresql://admin:password@ecs-postgres-db.xxx.ap-south-1.rds.amazonaws.com:5432/appdb
# Expected:
# postgres=#
Health Check:
// Add to app.js
app.get('/health', async (req, res) => {
try {
await pool.query('SELECT 1');
res.json({ status: 'healthy', database: 'connected' });
} catch (error) {
res.status(500).json({ status: 'unhealthy', database: error.message });
}
});
5. Database Backup & Auto-Scaling
Automated Backups (Already configured):
Retention: 7 days
Backup window: 03:00-04:00 UTC
Point-in-time recovery: Enabled
Manual Snapshot:
aws rds create-db-snapshot \
--db-instance-identifier ecs-postgres-db \
--db-snapshot-identifier backup-2025-06-04
Auto-Scaling Storage:
resource "aws_db_instance" "postgres" {
# ... (previous config)
allocated_storage = 20
storage_type = "gp2"
auto_minor_version_upgrade = true
# Enable storage auto-scaling
max_allocated_storage = 100 # Scale up to 100GB automatically
}
Summary
You now have production database integration:
✅ RDS PostgreSQL in private subnet
✅ Security Group (ECS → RDS only)
✅ AWS Secrets Manager for credentials
✅ App connected to database
✅ Automated backups (7-day retention)
✅ Storage auto-scaling
Next Step: Part 7 will add CI/CD with GitHub Actions (modern alternative to CodeDeploy).
About the author
- Hi, I'm Atul! I am a software engineer with a strong focus on DevOps, Cloud Infrastructure, and automation. I spend my time building scalable CI/CD pipelines, mastering tools like Docker, Terraform, and AWS, and breaking down complex cloud concepts into accessible, hands-on tutorials. I believe the best way to learn is to build, break, and document the process.
Comments
Join the discussionNo comments yet. Be the first to comment.
Zero to Production with AWS ECS Fargate: Terraform, CI/CD, RDS, Monitoring
A hands-on AWS ECS Fargate series that takes a containerized app from zero to production using Terraform, VPC networking, ECR, Application Load Balancer, blue-green deployments, CloudWatch monitoring, RDS PostgreSQL, Secrets Manager, and GitHub Actions CI/CD.





