AWS RDS
Overview
Section titled “Overview”This guide provisions an AWS RDS for PostgreSQL instance for the Governance Platform. For why to use an external database, the required platform databases, and the shared Helm configuration, see the External Database overview.
For Aurora PostgreSQL the steps are equivalent - create a cluster instead of an instance and use the cluster writer endpoint as the host.
Prerequisites
Section titled “Prerequisites”- Kubernetes cluster with network reachability to RDS (VPC peering, a transit gateway, or the cluster and instance in the same VPC)
- AWS CLI installed and configured with permissions to manage RDS and EC2 security groups
psqlclient available to create databaseskubectlaccess to the deployment namespace
Helm Configuration
Section titled “Helm Configuration”Use the shared configuration from the External Database overview with these RDS-specific values:
postgresql: enabled: false
global: postgresql: host: "<instance>.<region>.rds.amazonaws.com" # Filled in after step 2 port: 5432 database: "governance" username: "postgres" # Master username from step 2 sslMode: "verify-full" sslRootCert: secretName: "postgres-ca" # Created in step 4 key: "ca.crt"Set the master password from step 2 in the platform-database secret in secrets.yaml.
Quick Start (CLI Method - Recommended)
Section titled “Quick Start (CLI Method - Recommended)”1. Create Networking Resources
Section titled “1. Create Networking Resources”Create a DB subnet group and a security group that allows PostgreSQL traffic from the cluster:
# Set variablesexport AWS_REGION="us-east-1"export VPC_ID="<cluster-vpc-id>"export CLUSTER_SG_ID="<cluster-node-security-group-id>"
# Create a DB subnet group from the VPC's private subnetsaws rds create-db-subnet-group \ --db-subnet-group-name governance-platform-db \ --db-subnet-group-description "Governance Platform database subnets" \ --subnet-ids <private-subnet-1> <private-subnet-2> \ --region $AWS_REGION
# Create a security group for the databaseexport DB_SG_ID=$(aws ec2 create-security-group \ --group-name governance-platform-db \ --description "Governance Platform database" \ --vpc-id $VPC_ID \ --query 'GroupId' --output text)
# Allow PostgreSQL (5432) from the cluster nodes onlyaws ec2 authorize-security-group-ingress \ --group-id $DB_SG_ID \ --protocol tcp --port 5432 \ --source-group $CLUSTER_SG_ID2. Create the RDS Instance
Section titled “2. Create the RDS Instance”aws rds create-db-instance \ --db-instance-identifier governance-platform \ --engine postgres \ --engine-version 17.4 \ --db-instance-class db.t4g.medium \ --allocated-storage 50 \ --storage-type gp3 \ --storage-encrypted \ --master-username postgres \ --master-user-password "<master-password>" \ --db-subnet-group-name governance-platform-db \ --vpc-security-group-ids $DB_SG_ID \ --no-publicly-accessible \ --backup-retention-period 7 \ --region $AWS_REGIONWait for the instance to become available and note its endpoint:
aws rds wait db-instance-available \ --db-instance-identifier governance-platform
aws rds describe-db-instances \ --db-instance-identifier governance-platform \ --query 'DBInstances[0].Endpoint.Address' --output textThe endpoint is the global.postgresql.host value.
3. Create the Platform Databases
Section titled “3. Create the Platform Databases”Connect from a host that can reach the instance (for example, a bastion or a temporary pod in the cluster) and create both databases:
psql "host=<instance-endpoint> port=5432 user=postgres sslmode=require" <<'SQL'CREATE DATABASE governance;GRANT ALL PRIVILEGES ON DATABASE governance TO postgres;
CREATE DATABASE "IntegrityServiceDB";GRANT ALL PRIVILEGES ON DATABASE "IntegrityServiceDB" TO postgres;SQL4. Mount the RDS CA Bundle
Section titled “4. Mount the RDS CA Bundle”Required for sslMode: "verify-full" (recommended). Download the RDS certificate bundle and create a Kubernetes secret from it:
curl -sSo global-bundle.pem \ https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
kubectl create secret generic postgres-ca \ --from-file=ca.crt=global-bundle.pem \ --namespace governanceIf you skip this step, set sslMode: "require" and remove the sslRootCert block from values.yaml.
5. Update Chart Values
Section titled “5. Update Chart Values”Fill in the Helm Configuration with the instance endpoint and master password, then proceed to the Helm Deployment guide. On the next helm upgrade --install, the bundled PostgreSQL is not deployed and all services connect to the RDS instance.
Alternative: Web UI Setup
Section titled “Alternative: Web UI Setup”Using the AWS Console
Section titled “Using the AWS Console”- Navigate to RDS → Create database
- Choose Standard create → PostgreSQL, engine version 17.x
- Under Templates, choose Production (enables Multi-AZ and backups)
- Set the DB instance identifier, master username, and master password
- Under Connectivity, select the cluster’s VPC, choose No public access, and attach a security group that allows port 5432 from the cluster nodes
- Under Additional configuration, enable encryption and set the backup retention period
- Create the database, then follow steps 3-5 of the CLI method above
Verification
Section titled “Verification”Follow the verification steps in the External Database overview, using the RDS endpoint as the host. The database list must include both governance and IntegrityServiceDB.
Security Best Practices
Section titled “Security Best Practices”- Keep the instance private - no public accessibility; restrict the security group to the cluster nodes
- Use
sslMode: "verify-full"with the RDS CA bundle to prevent man-in-the-middle attacks - Enable storage encryption at rest when creating the instance (it cannot be enabled later on RDS)
- Enable deletion protection on the production instance (
--deletion-protection) - Store the master password only in
secrets.yamlor an approved secret manager - never invalues.yaml
Cost Considerations
Section titled “Cost Considerations”- The instance class dominates cost;
db.t4g.mediumis a reasonable starting point and can be resized later - Multi-AZ roughly doubles instance cost but is recommended for production
- Automated backup storage up to the size of the instance storage is included; snapshots beyond that are billed per GB
- gp3 storage can scale IOPS independently of size if the platform’s write load grows