The first-database quickstart in the Core Services section covered create, wait, connect, and delete. This page is the next layer: the everyday control-plane vocabulary you use to inspect, configure, and secure a database before snapshots, failover, and proxies make sense.
Each example is small and shows both the AWS SDK call and, where relevant, how the result feeds a normal SQL driver. Remember the model: the SDK manages the database as infrastructure; your app queries it with a driver over the endpoint. Read the examples in order - describe, then endpoints, then settings, then credentials.
DescribeDBInstances returns the full state of a database, including the endpoint your app connects to. This is the most common read on the control plane.
The endpoint from the previous step feeds a normal driver. This snippet is a driver connection, not an AWS SDK call - the SDK is done once you have the host.
# --- Python (psycopg2 driver - NOT the AWS SDK) ---import psycopg2# host/port came from DescribeDBInstances; the SDK plays no part in the query.conn = psycopg2.connect( host="app-db.abc123.us-east-1.rds.amazonaws.com", port=5432, user="appuser", password="from-secrets-manager", dbname="postgres",)with conn.cursor() as cur: cur.execute("SELECT now();") print(cur.fetchone()[0])conn.close()
This is psycopg2, a PostgreSQL driver - the AWS SDK has no query API for standard RDS.
The password should come from Secrets Manager (see example 5), never a literal in code.
The equivalent Node.js driver is pg; the shape is the same host/port/user/password.
For a connectionless alternative on Aurora, see the Aurora Data API page.
Aurora is described with DescribeDBClusters, which returns both the writer endpoint and the reader endpoint - the split that lets you route reads away from writes.
# --- Python (boto3) ---cl = rds.describe_db_clusters(DBClusterIdentifier="app-aurora")["DBClusters"][0]print("writer endpoint:", cl["Endpoint"]) # points at the current writerprint("reader endpoint:", cl["ReaderEndpoint"]) # load-balances across readersprint("members:", [m["DBInstanceIdentifier"] for m in cl["DBClusterMembers"]])
// --- TypeScript (AWS SDK v3) ---import { DescribeDBClustersCommand } from "@aws-sdk/client-rds";const out = await rds.send(new DescribeDBClustersCommand({ DBClusterIdentifier: "app-aurora" }));const cl = out.DBClusters![0];console.log("writer endpoint:", cl.Endpoint); // points at the current writerconsole.log("reader endpoint:", cl.ReaderEndpoint); // load-balances across readersconsole.log("members:", cl.DBClusterMembers?.map((m) => m.DBInstanceIdentifier));
Endpoint is the writer (cluster) endpoint; send writes and read-after-write here.
ReaderEndpoint load-balances read-only connections across all reader instances.
DBClusterMembers lists each instance and whether it is the writer (IsClusterWriter).
The endpoints are stable DNS names; they survive failover by repointing automatically.
ModifyDBInstance changes configuration - instance size, backup retention, Multi-AZ - after creation. ApplyImmediately decides whether the change happens now or in the next maintenance window.
# --- Python (boto3) ---rds.modify_db_instance( DBInstanceIdentifier="app-db", DBInstanceClass="db.t3.small", # scale up the compute BackupRetentionPeriod=7, # keep 7 days of automated backups ApplyImmediately=True, # False = wait for the maintenance window)
// --- TypeScript (AWS SDK v3) ---import { ModifyDBInstanceCommand } from "@aws-sdk/client-rds";await rds.send(new ModifyDBInstanceCommand({ DBInstanceIdentifier: "app-db", DBInstanceClass: "db.t3.small", // scale up the compute BackupRetentionPeriod: 7, // keep 7 days of automated backups ApplyImmediately: true, // false = wait for the maintenance window}));
ApplyImmediately=True can cause a brief outage for some changes (like an instance-class resize).
Leaving it False defers the change to the PreferredMaintenanceWindow, avoiding surprise downtime.
A BackupRetentionPeriod greater than 0 enables automated backups and point-in-time recovery.
The instance enters a modifying status; wait for available before assuming the change is live.
ManageMasterUserPassword tells RDS to generate, store, and rotate the master password in AWS Secrets Manager. Your app fetches the secret at connect time instead of hardcoding a password.
# --- Python (boto3) ---# 1. Provision with a managed master password (no password in code).rds.create_db_instance( DBInstanceIdentifier="secure-db", Engine="postgres", DBInstanceClass="db.t3.micro", AllocatedStorage=20, MasterUsername="appuser", ManageMasterUserPassword=True,)rds.get_waiter("db_instance_available").wait(DBInstanceIdentifier="secure-db")# 2. Find the secret ARN RDS created, then fetch it from Secrets Manager.inst = rds.describe_db_instances(DBInstanceIdentifier="secure-db")["DBInstances"][0]secret_arn = inst["MasterUserSecret"]["SecretArn"]import jsonsm = boto3.client("secretsmanager", region_name="us-east-1")creds = json.loads(sm.get_secret_value(SecretId=secret_arn)["SecretString"])print("username:", creds["username"]) # password is creds["password"]
// --- TypeScript (AWS SDK v3) ---import { CreateDBInstanceCommand, DescribeDBInstancesCommand, waitUntilDBInstanceAvailable } from "@aws-sdk/client-rds";import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";// 1. Provision with a managed master password (no password in code).await rds.send(new CreateDBInstanceCommand({ DBInstanceIdentifier: "secure-db", Engine: "postgres", DBInstanceClass: "db.t3.micro", AllocatedStorage: 20, MasterUsername: "appuser", ManageMasterUserPassword: true,}));await waitUntilDBInstanceAvailable({ client: rds, maxWaitTime: 900 }, { DBInstanceIdentifier: "secure-db" });// 2. Find the secret ARN RDS created, then fetch it from Secrets Manager.const out = await rds.send(new DescribeDBInstancesCommand({ DBInstanceIdentifier: "secure-db" }));const secretArn = out.DBInstances![0].MasterUserSecret!.SecretArn!;const sm = new SecretsManagerClient({ region: "us-east-1" });const secret = await sm.send(new GetSecretValueCommand({ SecretId: secretArn }));const creds = JSON.parse(secret.SecretString!);console.log("username:", creds.username); // password is creds.password
ManageMasterUserPassword removes the MasterUserPassword parameter entirely - nothing to leak.
RDS creates the secret and reports its ARN under MasterUserSecret.SecretArn.
RDS rotates the secret automatically; your driver should read it fresh, not cache it forever.
IAM database authentication is an alternative that issues short-lived tokens instead of a stored password.
Standard RDS databases (PostgreSQL, MySQL, MariaDB, Oracle, SQL Server) are instances: create and inspect them with CreateDBInstance and DescribeDBInstances, and there is exactly one endpoint. Aurora is a cluster: the storage lives in the cluster and compute is attached as instances, so you use DescribeDBClusters for the writer/reader endpoints and DescribeDBInstances for a specific member's status. A common mistake is calling DescribeDBInstances on an Aurora identifier and looking for a reader endpoint that only exists at the cluster level.
Almost every control-plane change moves the database through a transient status (creating, modifying, backing-up, rebooting) before returning to available. Never assume a change is complete when the call returns. Use the db_instance_available / db_cluster_available waiters, or poll DBInstanceStatus / Status, before the next step depends on the new state.
Reading the endpoint too early.Endpoint is absent while an instance is creating. Fix: wait on db_instance_available, then describe.
Looking for a reader endpoint on an instance. Only Aurora clusters have a ReaderEndpoint. Fix: use DescribeDBClusters for Aurora, not DescribeDBInstances.
ApplyImmediately surprises. Some modifications cause a brief outage when applied immediately. Fix: leave it false to defer to the maintenance window unless you need the change now.
Hardcoding the master password. A literal password leaks through source control and logs. Fix: use ManageMasterUserPassword and read the secret at connect time.
Expecting the SDK to run queries. There is no rds API to SELECT from a standard database. Fix: connect with psycopg2 / pg, or use the Aurora Data API.
Call DescribeDBInstances and read Endpoint.Address and Endpoint.Port. For Aurora, call DescribeDBClusters and read Endpoint (writer) and ReaderEndpoint (readers). The endpoint appears only once the database is available.
Does the SDK let me run SQL against a standard RDS instance?
No. For standard RDS you connect with a normal driver such as psycopg2 or pg over the endpoint. The only SDK-native SQL path is the Aurora Data API, which works on Aurora clusters configured for it.
What is the difference between DescribeDBInstances and DescribeDBClusters?
DescribeDBInstances returns individual database servers and their single endpoint. DescribeDBClusters returns Aurora clusters and exposes the writer and reader endpoints plus the list of member instances. Aurora needs both calls at different times.
When should I set ApplyImmediately to true?
Only when you accept the change - and any brief outage it may cause - happening now. Leaving it false defers the change to the preferred maintenance window, which is safer for production. Some changes always apply immediately regardless.
How does ManageMasterUserPassword work?
RDS generates the master password, stores it in AWS Secrets Manager, and reports the secret ARN under MasterUserSecret. It also rotates the secret automatically. Your app reads the current value from Secrets Manager at connect time instead of holding a password.
Why is my endpoint missing right after creating the instance?
Provisioning is asynchronous. The instance is still creating and has no endpoint yet. Wait on the db_instance_available waiter (or poll DBInstanceStatus until available) before reading Endpoint.
Can I change the instance size without downtime?
An instance-class resize typically involves a short outage when applied. On Multi-AZ the impact is reduced because AWS modifies the standby first and fails over. Aurora scales compute per instance and you can also add readers to absorb load.
Is IAM database authentication a replacement for the password?
Largely, yes. With IAM auth enabled, your driver requests a short-lived token from the SDK and presents it instead of a password. It avoids storing a long-lived credential but has a token lifetime and connection-rate considerations to plan for.