AWS RDS
Configure AWS RDS for PostgreSQL for deployment
Overview
This guide provisions an AWS RDS for PostgreSQL instance for the Guardian 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
- 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
Use the shared configuration from the External Database overview with these RDS-specific values:
postgresql:
enabled: false
global:
postgresql:
host: "<instance>.<id>.<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. When the gateway stack is enabled, also set gatewayDsn there, as shown in the External Database overview.
Quick Start (CLI Method - Recommended)
Create the networking and instance with the AWS CLI, create the platform databases with psql, and mount the RDS CA bundle, in five steps.
1. Create Networking Resources
Create a DB subnet group and a security group that allows PostgreSQL traffic from the cluster:
# Set variables
export 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 subnets
aws rds create-db-subnet-group \
--db-subnet-group-name guardian-platform-db \
--db-subnet-group-description "Guardian Platform database subnets" \
--subnet-ids <private-subnet-1> <private-subnet-2> \
--region $AWS_REGION
# Create a security group for the database
export DB_SG_ID=$(aws ec2 create-security-group \
--group-name guardian-platform-db \
--description "Guardian Platform database" \
--vpc-id $VPC_ID \
--query 'GroupId' --output text \
--region $AWS_REGION)
# Allow PostgreSQL (5432) from the cluster nodes only
aws ec2 authorize-security-group-ingress \
--group-id $DB_SG_ID \
--protocol tcp --port 5432 \
--source-group $CLUSTER_SG_ID \
--region $AWS_REGION2. Create the RDS Instance
aws rds create-db-instance \
--db-instance-identifier guardian-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 guardian-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 guardian-platform \
--region $AWS_REGION
aws rds describe-db-instances \
--db-instance-identifier guardian-platform \
--query 'DBInstances[0].Endpoint.Address' --output text \
--region $AWS_REGIONThe endpoint is the global.postgresql.host value.
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 the databases. Skip guardian_gateway unless the gateway stack is enabled:
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;
CREATE DATABASE guardian_gateway;
GRANT ALL PRIVILEGES ON DATABASE guardian_gateway TO postgres;
SQL4. 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 guardianIf you skip this step, set sslMode: "require" and remove the sslRootCert block from values.yaml.
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
The same setup can be done in the AWS Console instead of the CLI.
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
Follow the verification steps in the External Database overview, using the RDS endpoint as the host. The database list must include governance and IntegrityServiceDB, plus guardian_gateway when the gateway stack is enabled.
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
- 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
Official Documentation
- Amazon RDS for PostgreSQL User Guide
- Using SSL with an RDS DB Instance
- Amazon Aurora PostgreSQL
- Helm Chart Examples
Related
- External Database — the shared configuration and verification for any managed PostgreSQL
- Backup and Restore — automated backups and pre-upgrade snapshots for RDS
- AWS S3 Bucket — the AWS object storage the platform needs
- AWS KMS — the AWS key provider for DID signing keys
- Helm Deployment — deploying the platform against the new instance