Day 04 Day 4

Day 4

Day 4

~1 hour Intermediate Hands-on Precision AI Academy

Today's Objective

Launch a PostgreSQL RDS instance, connect to it securely with VPC, manage credentials with Secrets Manager, and run migrations.

RDS: Managed Relational Databases

RDS runs PostgreSQL, MySQL, and other databases without you managing the server. AWS handles backups, OS patching, failover, and disk expansion. You get the same Postgres you know — without the ops.

Launch a Postgres RDS Instance

terminal_-_create_rds_instance.txt
TERMINAL — CREATE RDS INSTANCE
aws rds create-db-instance \
  --db-instance-identifier myapp-postgres \
  --db-instance-class db.t3.micro \
  --engine postgres \
  --engine-version "15.4" \
  --master-username appuser \
  --master-user-password "$(openssl rand -base64 20)" \
  --allocated-storage 20 \
  --storage-type gp3 \
  --no-publicly-accessible \
  --vpc-security-group-ids sg-abc123 \
  --backup-retention-period 7 \
  --deletion-protection
Always use no-publicly-accessible. Your database should only be reachable from within your VPC — not from the public internet. Your App Runner service connects via VPC connector.

Store Credentials in Secrets Manager

terminal_-_store_rds_credentials.txt
TERMINAL — STORE RDS CREDENTIALS
aws secretsmanager create-secret \
  --name prod/rds/myapp \
  --secret-string '{
    "host": "myapp-postgres.xyz.us-east-1.rds.amazonaws.com",
    "port": 5432,
    "dbname": "myapp",
    "username": "appuser",
    "password": "your-generated-password"
  }'

Connect from Node.js

node.js_-_rds_connection_with_secrets_manager.txt
NODE.JS — RDS CONNECTION WITH SECRETS MANAGER
import pg from 'pg';
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';

const sm = new SecretsManagerClient({ region: 'us-east-1' });

async function getDbConfig() {
  const res = await sm.send(new GetSecretValueCommand({
    SecretId: 'prod/rds/myapp'
  }));
  return JSON.parse(res.SecretString);
}

let pool;
export async function getPool() {
  if (!pool) {
    const config = await getDbConfig();
    pool = new pg.Pool({
      host: config.host,
      port: config.port,
      database: config.dbname,
      user: config.username,
      password: config.password,
      ssl: { rejectUnauthorized: false }, // RDS requires SSL
      max: 10,
      idleTimeoutMillis: 30000,
    });
  }
  return pool;
}

// Usage
const pool = await getPool();
const result = await pool.query('SELECT NOW()');
console.log(result.rows[0]);

Run Migrations Safely

terminal_-_migrations_with_node-postgres.txt
TERMINAL — MIGRATIONS WITH NODE-POSTGRES
npm install node-pg-migrate

# package.json scripts
"migrate:up": "node-pg-migrate up",
"migrate:down": "node-pg-migrate down",
"migrate:create": "node-pg-migrate create"

# Run migrations against RDS (use the credentials from Secrets Manager)
DATABASE_URL="postgresql://appuser:pass@host:5432/myapp" npm run migrate:up
Day 4 Exercise
  1. Launch a db.t3.micro PostgreSQL 15 RDS instance in private mode
  2. Store the credentials in Secrets Manager under prod/rds/myapp
  3. Create a VPC connector for your App Runner service to reach RDS
  4. Connect from a Node.js script using the Secrets Manager integration
  5. Run a simple migration to create a users table

What's Next

The foundations from today carry directly into Day 5. In the next session the focus shifts to Day 5 — building directly on everything covered here.

Supporting Videos & Reading

Go deeper with these external references.

Day 4 Checkpoint

Before moving on, verify you can answer these without looking:

Live Bootcamp

Learn this in person — 2 days, 5 cities

Thu–Fri sessions in Denver, Los Angeles, New York, Chicago, and Dallas. $1,490 per seat. June–October 2026.

Reserve Your Seat →
Continue To Day 5
Day 5: Domains and HTTPS — Route 53, ACM, and CloudFront