Amazon Aurora

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

See the section bibliography for the reference material consulted while preparing these pages.

Commands and behaviour on this page are current for AWS CLI v2 (2.37 line) and the Aurora documentation as checked on 2026-10-01: Aurora Serverless v2 capacity of 0 to 256 ACUs with auto-pause on Aurora PostgreSQL 16.3, 15.7, 14.12 and version 13.15 or later and Aurora MySQL 3.08.0 or later, and Aurora DSQL (generally available since May 2025). Examples use us-east-1 and the placeholder account ID 111122223333; both are stand-ins for your own values. Engine minor versions change monthly, so every example asks the CLI for the versions that exist in your Region instead of hard-coding one.

Amazon Aurora is AWS’s cloud-native relational database, offered in two engine editions that speak the PostgreSQL and MySQL wire protocols. Instead of attaching a disk to one server, Aurora separates a fleet of database instances (compute) from one shared, distributed, self-healing cluster volume (storage). That separation is what makes adding a reader take minutes, failover take seconds, clones nearly instant and Serverless v2 possible. This page covers how the cluster is built, how to create one from the console and the CLI, the Serverless v2 capacity model (including scaling to zero), storage configurations, the Data API, Global Database and Limitless Database, the separate Aurora DSQL service, clones and backtrack, IAM authentication, networking, pricing drivers, troubleshooting and clean up. The running example is Bookshelf’s bookshelf-catalog cluster (database catalog, Aurora PostgreSQL Serverless v2, pgvector for similarity search) that the catalog-api service from ECS and Fargate connects to.

Plain Amazon RDS (a single instance or a Multi-AZ DB cluster on ordinary EBS storage) is covered on Amazon RDS; choosing between the AWS database services is on Managed Databases on AWS. For the Azure counterparts see PostgreSQL and MySQL on Azure and Managed Databases on Azure.

Architecture

Cluster volume, writer and readers

An Aurora DB cluster is made of up to 16 DB instances plus one cluster volume:

Cluster volume

A single virtual SSD-backed volume, replicated six ways across three Availability Zones in the Region regardless of how many instances exist. It grows automatically as data is added and releases space when data is dropped, up to 256 TiB on recent engine versions, and you pay only for what is used. It holds tables, indexes, system catalogs and, for MySQL, the binary log. Temporary files (sorts, index builds) live on the instance’s local storage instead.

Writer instance

The one instance that accepts writes and DDL. It ships redo log records, not data pages, to the storage layer, which materialises pages itself; this is why writes do not wait for checkpoints and why replicas add no write amplification.

Reader instances (Aurora Replicas)

Up to 15 read-only instances that attach to the same volume. Replica lag is typically tens of milliseconds because readers only have to invalidate or update their caches, not apply data. Each reader has a promotion tier (0 to 15); on failover Aurora promotes the lowest tier number, and a promotion usually completes in well under a minute.

Cluster endpoints

DNS names that follow the topology: the cluster (writer) endpoint always points at the current writer, the reader endpoint load-balances connections across readers, and custom endpoints name a subset of instances (for example the large readers used for reporting). Applications should use endpoints, never instance endpoints, so failover is transparent apart from dropped connections.

Diagram of an Aurora cluster with a writer in one Availability Zone and readers in two others, cluster endpoints above them, and below them one cluster volume holding six copies of the data across three zones

Durability uses a quorum: a write is acknowledged when four of the six copies have it and a read needs three. The loss of an entire Availability Zone plus one more copy still leaves the data readable, and storage repairs failed segments from the surviving copies in the background. Because the data copies exist independently of instances, deleting a reader never deletes data; only deleting the cluster does.

Aurora versus RDS versus the other Aurora family members

Option Compute model Storage and availability Choose it when

RDS for PostgreSQL / MySQL

One provisioned instance, optionally a standby (Multi-AZ) and read replicas with their own copies of the data.

EBS volumes (gp3, io2) sized in advance; failover to a standby that has its own copy.

Smaller or steady workloads, exact community-engine behaviour, lowest entry cost. See Amazon RDS.

Aurora provisioned

Fixed instance classes (for example Graviton db.r8g) for the writer and each reader.

Shared cluster volume, six copies, readers share it, fast failover, up to 15 readers.

Steady, performance-sensitive relational workloads that benefit from fast failover and many readers.

Aurora Serverless v2

Instances of class db.serverless whose capacity moves between a minimum and maximum number of ACUs, in increments as small as 0.5, while connections stay open. Can scale to zero and pause.

Same shared cluster volume.

Variable, spiky, unpredictable or intermittent workloads, dev and test, multi-tenant fleets. Bookshelf’s catalog.

Aurora Global Database

A primary cluster plus up to several read-only secondary clusters in other Regions.

Storage-level replication, typically under a second of lag; cross-Region failover or switchover.

Disaster recovery across Regions, local reads for users abroad.

Aurora Limitless Database

A sharded PostgreSQL-compatible cluster that scales writes horizontally across many routers and shards.

Managed horizontal partitioning.

Write throughput or data size beyond a single writer.

Aurora DSQL

A separate, serverless, distributed SQL service with no instances to size or patch. Active-active across Regions.

Managed by the service; strongly consistent across Regions.

Very high availability across Regions with PostgreSQL-compatible SQL and an application that tolerates optimistic concurrency retries.

The comparison of the three Aurora compute shapes Bookshelf could pick between:

flowchart TD A["Need a managed PostgreSQL or MySQL database"] --> B{"Multi-Region active-active writes and no instance management?"} B -- "yes, and DSQL's SQL subset is enough" --> DSQL["Aurora DSQL: serverless, distributed, PostgreSQL-compatible"] B -- "no" --> C{"Is the load steady and predictable?"} C -- "yes" --> P["Aurora provisioned: fixed db.r-class instances, Reserved Instances possible"] C -- "no: spiky, idle at night, many small tenants" --> S["Aurora Serverless v2: ACU range, optional scale to zero"] P --> M{"Writes outgrow one writer?"} S --> M M -- "yes" --> L["Aurora Limitless Database"] M -- "no" --> G{"Need a second Region?"} G -- "yes" --> GD["Add an Aurora Global Database secondary"] G -- "no" --> OK["Single-Region cluster, writer plus readers across AZs"]

Editions and versions

Aurora PostgreSQL tracks community PostgreSQL major versions (several are available at any time) and supports the extensions most applications need, including pgvector for embeddings (see PostgreSQL & pgvector). Aurora MySQL 3 is compatible with MySQL 8.0; newer MySQL compatibility lines appear on the Aurora MySQL release notes, and older majors (PostgreSQL 11 and 12, MySQL 5.7 compatible Aurora MySQL 2) are past standard support, where Extended Support fees apply if you keep running them. Older guides still show Aurora with those versions and with --engine-mode serverless clusters; both are outdated.

List what your Region offers instead of copying a version number from a tutorial:

export AWS_REGION=us-east-1

aws rds describe-db-engine-versions --engine aurora-postgresql \
  --query 'DBEngineVersions[].EngineVersion' --output text | tr '\t' '\n' | tail -n 8

# only versions that can run Serverless v2 with auto-pause (MinCapacity 0)
aws rds describe-db-engine-versions --engine aurora-postgresql \
  --query 'DBEngineVersions[?ServerlessV2FeaturesSupport.MinCapacity==`0`].EngineVersion' --output text

aws rds describe-orderable-db-instance-options --engine aurora-postgresql \
  --db-instance-class db.serverless --query 'OrderableDBInstanceOptions[0].EngineVersion'

Derived from aws rds describe-db-engine-versions, Database engine updates for Amazon Aurora PostgreSQL and Database engine updates for Amazon Aurora MySQL. A version supports auto-pause when ServerlessV2FeaturesSupport.MinCapacity is 0; if the structure is absent from your CLI’s output, upgrade the CLI or use the version table in the Serverless v2 capacity documentation.

Storage configurations: Standard and I/O-Optimized

Every cluster uses one of two storage configurations, selected with the CLI --storage-type value:

Console name --storage-type Billing shape

Aurora Standard

aurora

Instance (or ACU) hours, storage per GB-month, plus a per-million-requests charge for I/O. Cheaper when I/O is moderate.

Aurora I/O-Optimized

aurora-iopt1

Higher instance (or ACU) and storage rates but no per-request I/O charge; predictable. AWS’s guideline is that it pays off when I/O spend is about a quarter or more of the total Aurora bill.

You can switch from Standard to I/O-Optimized once every 30 days, and back at any time; for Serverless v2 (and other non-NVMe) instances no restart is needed. Check the cost split first (VolumeReadIOPs, VolumeWriteIOPs in CloudWatch, or Cost Explorer’s Aurora I/O usage type) rather than guessing. Bookshelf starts on Standard and is revisited after a month of real traffic.

Aurora Serverless v2

Aurora Serverless v2 is a compute mode of ordinary Aurora clusters, not a separate product. You give each cluster a capacity range in Aurora capacity units (ACUs: roughly 2 GiB of memory plus matching CPU and networking) and every Serverless v2 instance in the cluster scales itself between the minimum and maximum, measured every second, without dropping connections or waiting for a quiet moment. It is the right default for new variable workloads, and it replaced Aurora Serverless v1.

Aurora Serverless v1 (--engine-mode serverless, --scaling-configuration, the "capacity pause" with connection-draining scaling, Data API only on v1) reached end of life on 2025-03-31 and no longer exists. Older guides and tutorials that create serverless engine-mode clusters, or that call it "Aurora Serverless" without a version, describe that retired product; the current equivalent is Serverless v2, which scales in place, supports readers, Multi-AZ, Global Database, IAM authentication and the Data API, and can pause when idle.

Capacity model

  • Range. The minimum can be 0 (auto-pause) or 0.5 and up; the maximum goes up to 256 ACUs. A minimum of 0 needs the engine versions listed in the intro; older versions bottom out at 0.5 ACUs, and some older engine versions top out at 128 ACUs. The platform version also matters and Aurora upgrades it with maintenance, a restart or a blue/green deployment.

  • Granularity. Scaling happens in steps as small as 0.5 ACUs; the larger the current capacity, the larger and faster the step. Scale-up is quick; scale-down is deliberately gradual.

  • Per instance. Each writer and reader scales on its own within the same range. A reader in promotion tier 0 or 1 tracks the writer’s capacity (so a failover target is never smaller than the writer); readers in tiers 2 to 15 scale independently, which suits reporting readers.

  • Mixed clusters. A cluster may combine provisioned and db.serverless instances, for example a large provisioned writer with serverless readers, or the reverse.

  • Parameters. Memory-related parameters scale with capacity, while max_connections is derived from the maximum ACU setting so connections do not drop when the instance scales down. A tiny maximum therefore means a low connection limit; size it for the number of pooled connections catalog-api opens.

  • Buffer cache. A minimum that is too low discards the cache during idle periods and makes the first queries after a quiet spell slow. Pick a minimum large enough to hold the working set.

Scaling to zero (auto-pause)

With a minimum capacity of 0, an instance pauses after a configurable idle period (SecondsUntilAutoPause, minimum 300 seconds, default 300, maximum 86,400) with no user-initiated connections, and instance charges stop (storage and backups are still billed). A connection attempt, a Data API call, a parameter group change, a clone, a backtrack request or an upgrade resumes it. Details that matter in practice:

  • Typical resume time is about 15 seconds; after more than 24 hours paused it can be 30 seconds or more. Make client connect timeouts longer than that (for the PostgreSQL JDBC driver connectTimeout, with retry logic).

  • After resuming it starts at a small capacity and scales up, not at the capacity it had before pausing.

  • The writer and all readers in promotion tiers 0 and 1 pause and resume together; readers in tiers 2 to 15 can pause independently, but resuming any reader resumes the writer.

  • It does not pause while any user connection is open, while an RDS Proxy is attached (the proxy holds connections), on the primary or secondary cluster of a Global Database, with logical replication or MySQL binlog enabled on the writer and tier 0 and 1 readers, with a zero-ETL integration to Amazon Redshift, or when any provisioned instance is in the cluster.

  • Scheduled jobs inside the database (pg_cron, the MySQL event scheduler) do not wake an instance and are skipped while paused.

So the Bookshelf production cluster uses a minimum of 0.5 ACUs (always on, fast), while the development and staging clusters use a minimum of 0 with a 10-minute pause.

Creating the Bookshelf catalog cluster

Prerequisites: a VPC with private subnets in at least two (ideally three) Availability Zones (see VPC Networking), and a security group for the application tier. Aurora needs a DB subnet group listing those subnets; the cluster’s instances are placed in them and the subnet group cannot span VPCs.

In the AWS Management Console

  1. Open Amazon RDS in the us-east-1 Region (check the Region selector) and choose Create database.

  2. Choose Standard create, engine type Aurora (PostgreSQL Compatible), and an engine version that supports Serverless v2 and, for scale to zero, auto-pause. Leave the Aurora Standard or Aurora I/O-Optimized storage option on Aurora Standard for now.

  3. Choose a template (Dev/Test or Production; Production preselects Multi-AZ). Name the cluster bookshelf-catalog.

  4. Under Credentials settings keep the master user name bookshelf_admin and choose Managed in AWS Secrets Manager. RDS creates and rotates the secret for you and the password never appears in a template or shell history. Use the default AWS managed key or pick your own KMS key.

  5. Under Instance configuration choose Serverless v2, set Minimum capacity (0 for dev, 0.5 for production) and Maximum capacity (for example 8). If the minimum is 0, set the idle time before pause.

  6. Under Availability & durability choose to create an Aurora Replica in a different Availability Zone for production; none is fine for development.

  7. Under Connectivity choose the VPC, the DB subnet group, Public access: No and a VPC security group that allows inbound TCP 5432 only from the application security group. Optionally tick Enable the RDS Data API.

  8. Under Database authentication choose Password and IAM database authentication. Under Additional configuration set the Initial database name to catalog, the backup retention period, encryption (on by default), log exports to CloudWatch Logs and Enable deletion protection for production.

  9. Review the estimated cost panel and choose Create database. The cluster and its first instance become Available after several minutes; the cluster page then shows the writer and reader endpoints.

With the AWS CLI

export AWS_REGION=us-east-1
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export VPC_ID=vpc-0123456789abcdef0                       # placeholder: your VPC
export DB_SUBNETS="subnet-0a1b2c3d4e5f60718 subnet-0f1e2d3c4b5a69788 subnet-0a9b8c7d6e5f40312"  # placeholders, one per AZ
export APP_SG=sg-0123456789abcdef0                        # placeholder: catalog-api task security group

# 1. Subnet group and a security group that only the application may reach
aws rds create-db-subnet-group \
  --db-subnet-group-name bookshelf-db-subnets \
  --db-subnet-group-description "Bookshelf private database subnets" \
  --subnet-ids $DB_SUBNETS

DB_SG=$(aws ec2 create-security-group --group-name bookshelf-catalog-db \
  --description "Aurora bookshelf-catalog" --vpc-id "$VPC_ID" --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$DB_SG" \
  --protocol tcp --port 5432 --source-group "$APP_SG"

# 2. The cluster: Serverless v2 range 0.5-8 ACU, RDS-managed master password in Secrets Manager
aws rds create-db-cluster \
  --db-cluster-identifier bookshelf-catalog \
  --engine aurora-postgresql \
  --database-name catalog \
  --master-username bookshelf_admin \
  --manage-master-user-password \
  --serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=8 \
  --db-subnet-group-name bookshelf-db-subnets \
  --vpc-security-group-ids "$DB_SG" \
  --storage-encrypted \
  --enable-iam-database-authentication \
  --backup-retention-period 7 \
  --enable-cloudwatch-logs-exports postgresql \
  --deletion-protection \
  --tags Key=app,Value=bookshelf

# 3. Instances: a serverless writer and a serverless reader in another AZ (promotion tier 1)
aws rds create-db-instance --db-instance-identifier bookshelf-catalog-1 \
  --db-cluster-identifier bookshelf-catalog --engine aurora-postgresql \
  --db-instance-class db.serverless --promotion-tier 1
aws rds create-db-instance --db-instance-identifier bookshelf-catalog-2 \
  --db-cluster-identifier bookshelf-catalog --engine aurora-postgresql \
  --db-instance-class db.serverless --promotion-tier 1

aws rds wait db-instance-available --db-instance-identifier bookshelf-catalog-1
aws rds wait db-instance-available --db-instance-identifier bookshelf-catalog-2

# 4. Endpoints and the managed secret
aws rds describe-db-clusters --db-cluster-identifier bookshelf-catalog \
  --query 'DBClusters[0].[Endpoint,ReaderEndpoint,MasterUserSecret.SecretArn,ServerlessV2ScalingConfiguration]'

Notes on those commands. Without --availability-zone Aurora spreads instances across the subnet group’s zones; the cluster volume spans three zones either way. --manage-master-user-password replaces the older pattern of generating a password and wiring up a hand-built rotation function: RDS stores the secret in Secrets Manager (named rds!cluster-…​, owned by RDS, rotation handled by RDS) and the console and describe-db-clusters show its ARN; applications read it by that ARN, and its consumption by ECS, Lambda and EKS is on Secrets Manager, Parameter Store and KMS. The secret is not bookshelf/catalog/db; if the application expects that name, copy only the connection details (host, port, database) there and keep the password secret referenced by ARN, or use IAM authentication so there is no password at all. Add --no-deletion-protection for disposable test clusters.

Connecting and creating the schema

Reach the private cluster from inside the VPC: a Session Manager port-forwarding session through a small EC2 instance, Client VPN (VPN and Hybrid Connectivity), or CloudShell attached to the VPC. Do not make the cluster public to run a one-off script.

WRITER=$(aws rds describe-db-clusters --db-cluster-identifier bookshelf-catalog \
  --query 'DBClusters[0].Endpoint' --output text)
SECRET_ARN=$(aws rds describe-db-clusters --db-cluster-identifier bookshelf-catalog \
  --query 'DBClusters[0].MasterUserSecret.SecretArn' --output text)
export PGPASSWORD=$(aws secretsmanager get-secret-value --secret-id "$SECRET_ARN" \
  --query SecretString --output text | python3 -c 'import sys,json; print(json.load(sys.stdin)["password"])')

psql "host=$WRITER port=5432 dbname=catalog user=bookshelf_admin sslmode=verify-full sslrootcert=global-bundle.pem" <<'SQL'
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE IF NOT EXISTS books (
  id         bigserial PRIMARY KEY,
  isbn       text UNIQUE NOT NULL,
  title      text NOT NULL,
  embedding  vector(384)
);
CREATE INDEX IF NOT EXISTS books_embedding_hnsw ON books USING hnsw (embedding vector_cosine_ops);
CREATE ROLE catalog_app LOGIN;
GRANT rds_iam TO catalog_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO catalog_app;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO catalog_app;
SQL
unset PGPASSWORD

Download the CA bundle (global-bundle.pem) from the Using SSL/TLS to encrypt a connection to a DB cluster page and keep sslmode=verify-full. The psql snippet reads the password into an environment variable for the session only and unsets it; never write it to a file or a task definition. The schema, types, operators and HNSW versus IVFFlat trade-offs for the embedding column are in PostgreSQL & pgvector, the SQL itself in Data Definition Language (DDL) and Data Control Language (DCL), and transactions in Transaction Control. Granting the rds_iam role to catalog_app is what makes IAM authentication work for that user (next sections).

Changing capacity, adding readers, failing over

# Change the Serverless v2 range (also turns scale-to-zero on or off)
aws rds modify-db-cluster --db-cluster-identifier bookshelf-catalog \
  --serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=16 --apply-immediately

# Dev cluster: scale to zero after 10 minutes idle
aws rds modify-db-cluster --db-cluster-identifier bookshelf-catalog-dev \
  --serverless-v2-scaling-configuration MinCapacity=0,MaxCapacity=4,SecondsUntilAutoPause=600

# Add an independent, pausable reporting reader (promotion tier 2-15)
aws rds create-db-instance --db-instance-identifier bookshelf-catalog-reports \
  --db-cluster-identifier bookshelf-catalog --engine aurora-postgresql \
  --db-instance-class db.serverless --promotion-tier 5

# Custom endpoint that exposes only the reporting reader
aws rds create-db-cluster-endpoint --db-cluster-identifier bookshelf-catalog \
  --db-cluster-endpoint-identifier reports --endpoint-type READER \
  --static-members bookshelf-catalog-reports

# Test failover: the tier-1 reader is promoted, the cluster endpoint follows
aws rds failover-db-cluster --db-cluster-identifier bookshelf-catalog

# Watch what the capacity actually did
aws cloudwatch get-metric-statistics --namespace AWS/RDS --metric-name ServerlessDatabaseCapacity \
  --dimensions Name=DBInstanceIdentifier,Value=bookshelf-catalog-1 \
  --start-time "$(date -u -v-1H +%FT%TZ)" --end-time "$(date -u +%FT%TZ)" \
  --period 300 --statistics Minimum Maximum Average

Derived from aws rds modify-db-cluster, aws rds create-db-cluster-endpoint and aws rds failover-db-cluster. The date -v-1H form is macOS; on Linux use date -u -d '1 hour ago' +%FT%TZ. In the console: RDS → Databases → select the cluster → Modify for the capacity range, Actions → Add reader, Actions → Failover and Actions → Create custom endpoint. A cluster with a db.serverless writer and a minimum of 0 ACUs only pauses when every instance in promotion tiers 0 and 1 is idle; the CloudWatch metrics ServerlessDatabaseCapacity and ACUUtilization tell you whether the range is too narrow (pinned at the maximum) or too wide.

RDS Data API

The RDS Data API lets code run SQL over HTTPS through the AWS API with no persistent database connection, no driver and no VPC attachment: callers authenticate with IAM and the database credentials come from a Secrets Manager secret. It works on Aurora PostgreSQL and Aurora MySQL clusters, both provisioned and Serverless v2, in supported Regions and engine versions. Older guides present the Data API as a Serverless v1 feature; it now works on v2 and provisioned clusters, which makes it a good fit for Lambda functions that would otherwise exhaust connections or need VPC networking, for quick administration scripts, and for the console’s query editor. It is not meant for high-throughput, low-latency application traffic (each call is an API request and results are size-limited), and calling it wakes an auto-paused instance.

CLUSTER_ARN=arn:aws:rds:us-east-1:111122223333:cluster:bookshelf-catalog

aws rds enable-http-endpoint --resource-arn "$CLUSTER_ARN"       # or --enable-http-endpoint at create time

aws rds-data execute-statement \
  --resource-arn "$CLUSTER_ARN" \
  --secret-arn "$SECRET_ARN" \
  --database catalog \
  --sql "SELECT isbn, title FROM books WHERE title ILIKE :q LIMIT 5" \
  --parameters '[{"name":"q","value":{"stringValue":"%sql%"}}]' \
  --format-records-as JSON

Derived from Using the Amazon RDS Data API, Enabling the Amazon RDS Data API and aws rds-data execute-statement. In the console tick Enable the RDS Data API under Connectivity when creating the cluster, or choose Actions → Enable RDS Data API on an existing one, then use Query editor in the RDS console. The caller needs rds-data permissions (policy below) plus secretsmanager:GetSecretValue on the secret; the RDS-managed master secret works for this. The Java SDK equivalent:

import software.amazon.awssdk.services.rdsdata.RdsDataClient;
import software.amazon.awssdk.services.rdsdata.model.*;

try (RdsDataClient data = RdsDataClient.create()) {   // default credential chain: task or execution role
    ExecuteStatementResponse r = data.executeStatement(ExecuteStatementRequest.builder()
            .resourceArn(System.getenv("CLUSTER_ARN"))
            .secretArn(System.getenv("SECRET_ARN"))
            .database("catalog")
            .sql("SELECT isbn, title FROM books WHERE id = :id")
            .parameters(SqlParameter.builder().name("id")
                    .value(Field.builder().longValue(42L).build()).build())
            .build());
    r.records().forEach(row -> System.out.println(row.get(1).stringValue()));
}

Authentication, IAM policies and secrets

Three credential models exist, and they combine:

Model How it works Use it for

Password in Secrets Manager (managed master password)

--manage-master-user-password; RDS owns and rotates the secret; clients fetch it.

Administrative access, migrations, tools that cannot do IAM.

IAM database authentication

The client calls aws rds generate-db-auth-token (or the SDK) and uses the 15-minute token as the password over TLS; the DB user is granted rds_iam (PostgreSQL) or created IDENTIFIED WITH AWSAuthenticationPlugin (MySQL).

Applications on ECS, Lambda or EKS: no stored password, access governed by the task or pod role.

Data API

IAM permission to call rds-data, plus a secret ARN.

Connectionless access from Lambda and scripts.

Three small policies cover Bookshelf. The operator who builds and changes the cluster (bookshelf-db-admin):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ManageBookshelfAuroraClusters",
      "Effect": "Allow",
      "Action": [
        "rds:CreateDBCluster", "rds:ModifyDBCluster", "rds:DeleteDBCluster",
        "rds:CreateDBInstance", "rds:ModifyDBInstance", "rds:DeleteDBInstance",
        "rds:FailoverDBCluster", "rds:RebootDBInstance",
        "rds:CreateDBClusterSnapshot", "rds:RestoreDBClusterToPointInTime",
        "rds:BacktrackDBCluster", "rds:AddTagsToResource"
      ],
      "Resource": [
        "arn:aws:rds:us-east-1:111122223333:cluster:bookshelf-*",
        "arn:aws:rds:us-east-1:111122223333:db:bookshelf-*",
        "arn:aws:rds:us-east-1:111122223333:cluster-snapshot:bookshelf-*",
        "arn:aws:rds:us-east-1:111122223333:subgrp:bookshelf-db-subnets",
        "arn:aws:rds:us-east-1:111122223333:pg:default.*",
        "arn:aws:rds:us-east-1:111122223333:cluster-pg:default.*"
      ]
    },
    {
      "Sid": "DescribeAndSubnetGroups",
      "Effect": "Allow",
      "Action": ["rds:Describe*", "rds:ListTagsForResource", "rds:CreateDBSubnetGroup"],
      "Resource": "*"
    }
  ]
}

The catalog-api task role, using IAM authentication as the database user catalog_app. The resource is the cluster’s resource ID (cluster- followed by an opaque string), not its name; read it with aws rds describe-db-clusters --query 'DBClusters[0].DbClusterResourceId':

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ConnectAsCatalogApp",
    "Effect": "Allow",
    "Action": "rds-db:connect",
    "Resource": "arn:aws:rds-db:us-east-1:111122223333:dbuser:cluster-ABCDEFGHIJKLMNOPQRSTUVWXYZ/catalog_app"
  }]
}

A Lambda or script using the Data API:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RunSqlThroughDataApi",
      "Effect": "Allow",
      "Action": [
        "rds-data:ExecuteStatement", "rds-data:BatchExecuteStatement",
        "rds-data:BeginTransaction", "rds-data:CommitTransaction", "rds-data:RollbackTransaction"
      ],
      "Resource": "arn:aws:rds:us-east-1:111122223333:cluster:bookshelf-catalog"
    },
    {
      "Sid": "ReadTheClusterSecret",
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:us-east-1:111122223333:secret:rds!cluster-*"
    }
  ]
}

Derived from Creating and using an IAM policy for IAM database access, Authorizing access to the Amazon RDS Data API and Actions, resources, and condition keys for Amazon RDS. Narrow the secret ARN to the specific rds!cluster-<id> secret once it exists. Generate and use an IAM token from the CLI to prove the path end to end:

TOKEN=$(aws rds generate-db-auth-token --hostname "$WRITER" --port 5432 \
  --region us-east-1 --username catalog_app)
PGPASSWORD="$TOKEN" psql "host=$WRITER port=5432 dbname=catalog user=catalog_app sslmode=verify-full sslrootcert=global-bundle.pem" -c 'select current_user'

Derived from aws rds generate-db-auth-token. Tokens last 15 minutes and are only checked when a connection is opened, so an existing connection survives expiry. IAM authentication has a connections-per-second ceiling per instance, which is one more reason to pool.

Spring Boot datasource (Bookshelf catalog-api)

Use the AWS Advanced JDBC Wrapper, which adds IAM-token refresh, Secrets Manager credentials and fast failover aware of Aurora topology on top of the normal PostgreSQL driver (add software.amazon.jdbc:aws-advanced-jdbc-wrapper and the AWS SDK rds module to the build). The task role from the policy above supplies credentials through the default chain:

spring:
  datasource:
    url: jdbc:aws-wrapper:postgresql://bookshelf-catalog.cluster-xxxx.us-east-1.rds.amazonaws.com:5432/catalog?wrapperPlugins=iam,failover2,efm2&sslmode=verify-full
    username: catalog_app
    driver-class-name: software.amazon.jdbc.Driver
    hikari:
      maximum-pool-size: 10
      max-lifetime: 600000     # below the 15-minute token lifetime
      connection-timeout: 30000   # longer than an auto-pause resume

Without IAM, replace the iam plugin with awsSecretsManager and the secretsManagerSecretId property (the RDS managed secret’s ARN). The wrapper keeps an internal view of the writer and readers, so after a failover it reconnects to the new writer without waiting for DNS to change. For general Spring Boot data-source, profile and secrets handling see Configuration and Profiles, and for the broader secrets workflow Secrets Manager, Parameter Store and KMS.

Networking

  • Private by default. Place the cluster in private subnets (a DB subnet group spanning at least two Availability Zones, three for the full benefit), set PubliclyAccessible to false for every instance, and use a dedicated security group that allows the database port (5432 for PostgreSQL, 3306 for MySQL) only from the application’s security group. Security groups are stateful; NACLs rarely need to change.

  • Reaching it from people. Session Manager port forwarding, Client VPN or a bastion with SSM; see VPN and Hybrid Connectivity. An internet-facing Aurora instance is almost never necessary.

  • From other VPCs and accounts. Peering or Transit Gateway (VPC Networking); the endpoint DNS name resolves to private addresses.

  • From AWS services without a VPC. The Data API’s HTTPS endpoint, optionally through an interface VPC endpoint (AWS PrivateLink, service rds-data), so Lambda functions need no VPC attachment or NAT gateway.

  • RDS Proxy. Pools and multiplexes connections for bursty clients such as Lambda and supports IAM and Secrets Manager credentials; it prevents Serverless v2 auto-pause, so it suits provisioned or always-on clusters (Amazon RDS covers it in depth).

  • IPv6. Dual-stack cluster endpoints are available on supported engine versions (--network-type DUAL).

  • Encryption. Storage encryption (KMS) is chosen at creation and cannot be turned on for an existing cluster except by restoring an encrypted copy of a snapshot; always connect with TLS and verify the certificate.

Backups, clones and backtrack

Aurora backs the cluster volume up continuously and incrementally to S3 and offers point-in-time restore anywhere in the retention window (1 to 35 days); the backup does not hit the writer. Manual cluster snapshots persist until deleted and can be copied or shared across Regions and accounts. A restore always creates a new cluster; you then point the application at it.

Clones

A clone is a new cluster that initially shares the source’s storage pages and writes copy-on-write, so a terabyte-sized database is cloned in minutes and costs only the changed pages. Use clones for staging copies of production data, migration rehearsals and heavy analytical queries that must not touch the production writer. A clone is independent of the source after creation, may be in the same account or shared with another one, and needs its own instances.

# Clone production into a throwaway test cluster (same VPC, same subnet group)
aws rds restore-db-cluster-to-point-in-time \
  --source-db-cluster-identifier bookshelf-catalog \
  --db-cluster-identifier bookshelf-catalog-clone \
  --restore-type copy-on-write --use-latest-restorable-time \
  --db-subnet-group-name bookshelf-db-subnets --vpc-security-group-ids "$DB_SG" \
  --serverless-v2-scaling-configuration MinCapacity=0,MaxCapacity=4,SecondsUntilAutoPause=600
aws rds create-db-instance --db-instance-identifier bookshelf-catalog-clone-1 \
  --db-cluster-identifier bookshelf-catalog-clone --engine aurora-postgresql --db-instance-class db.serverless

# Point-in-time restore to a full copy at a past time
aws rds restore-db-cluster-to-point-in-time \
  --source-db-cluster-identifier bookshelf-catalog --db-cluster-identifier bookshelf-catalog-restored \
  --restore-type full-copy --restore-to-time 2026-09-30T10:15:00Z \
  --db-subnet-group-name bookshelf-db-subnets --vpc-security-group-ids "$DB_SG"

# Manual snapshot, and a cross-Region copy for disaster recovery
aws rds create-db-cluster-snapshot --db-cluster-identifier bookshelf-catalog \
  --db-cluster-snapshot-identifier bookshelf-catalog-pre-migration

Derived from Cloning a volume for an Aurora DB cluster, aws rds restore-db-cluster-to-point-in-time and Restoring a DB cluster to a specified time. In the console choose Actions → Create clone (or Restore to point in time) on the cluster. After a restore or clone, create instances, then re-check parameter groups, security groups, IAM authentication and Data API settings, which are not all inherited.

Backtrack (Aurora MySQL only)

Backtrack rewinds a MySQL-compatible cluster to an earlier moment in place, in seconds, without restoring from a backup, which is ideal for undoing a bad DELETE or schema change. It is enabled at creation with a backtrack window and is not available on Aurora PostgreSQL (there use point-in-time restore or a clone) and not on every engine version; check the feature-compatibility list before combining it with other features. Backtrack records change data that is billed.

aws rds create-db-cluster --db-cluster-identifier bookshelf-orders-mysql --engine aurora-mysql \
  --master-username admin --manage-master-user-password --backtrack-window 86400 \
  --db-subnet-group-name bookshelf-db-subnets --vpc-security-group-ids "$DB_SG"

aws rds backtrack-db-cluster --db-cluster-identifier bookshelf-orders-mysql \
  --backtrack-to 2026-09-30T10:15:00Z

Scale-out and distribution options

Aurora Global Database

One primary cluster in a Region plus read-only secondary clusters in other Regions, replicated at the storage layer with typically sub-second lag and no impact on the primary’s performance. Use it for cross-Region disaster recovery (managed switchover for planned moves, failover for outages) and low-latency local reads. Serverless v2 works in the primary and secondaries; neither pauses while part of a global database. Writes to secondaries are forwarded to the primary only if you enable write forwarding.

aws rds create-global-cluster --global-cluster-identifier bookshelf-global \
  --source-db-cluster-identifier arn:aws:rds:us-east-1:111122223333:cluster:bookshelf-catalog

aws rds create-db-cluster --region us-west-2 --db-cluster-identifier bookshelf-catalog-usw2 \
  --global-cluster-identifier bookshelf-global --engine aurora-postgresql \
  --serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=8 \
  --db-subnet-group-name bookshelf-db-subnets-usw2

Derived from Using Amazon Aurora Global Database. Secondary clusters in another Region need that Region’s subnet group, a KMS key there if encrypted, and their own instances.

Aurora Limitless Database

A PostgreSQL-compatible, horizontally sharded mode (cluster scalability type limitless) that spreads tables across many shards behind transaction routers for write throughput and data size beyond one writer, with capacity measured in ACUs. Choose it only after a single, well-indexed writer on the largest Serverless v2 or provisioned class is not enough; it adds sharding-key design and has its own restrictions. See Amazon Aurora Limitless Database.

Other features

Zero-ETL integrations replicate transactional data into Amazon Redshift and other analytics targets without a pipeline (note they stop writers from auto-pausing); Blue/Green Deployments stage major-version upgrades and parameter changes on a copy of the cluster and switch over in about a minute; machine-learning integrations and Babelfish for Aurora PostgreSQL (T-SQL compatibility) exist for specific migrations.

Aurora DSQL

Amazon Aurora DSQL (generally available since May 2025) is a different service from Aurora clusters despite the name: a serverless, distributed SQL database with PostgreSQL-compatible syntax and wire protocol, no instances, no cluster volume to size, no patching and no failover to manage, built so that a multi-Region cluster is active-active: you can read and write on either Regional endpoint with strong consistency, with a third witness Region that holds a limited transaction log for quorum but no client endpoint.

What it is good at: applications that need very high availability and low-latency writes in more than one Region, unpredictable or spiky traffic with scale to zero, and no database operations. What it is not: a drop-in replacement for every PostgreSQL feature. Always check the current compatibility page before choosing it; at the time of checking it differs from PostgreSQL in these ways:

  • One built-in database named postgres per cluster (use schemas, or one cluster per logical database); C collation; UTC.

  • Optimistic concurrency control: there are no row locks, conflicting transactions fail at commit with a serialization error (SQLSTATE 40001), so application code must retry. Isolation is fixed at repeatable read. Spread writes over random keys (UUIDs) to reduce contention.

  • A transaction may modify at most 3,000 rows; DDL and DML cannot share a transaction, and one DDL statement per transaction; connections time out after an hour.

  • No triggers, no temporary tables, no procedural languages such as PL/pgSQL (SQL functions are supported), no TRUNCATE, no extensions such as pgvector (so Bookshelf’s similarity search stays on Aurora PostgreSQL), and CREATE INDEX ASYNC replaces CREATE INDEX. Foreign keys, sequences and identity columns are supported on current releases; check the linked pages for specifics and limits.

  • Authentication is IAM only: there are no passwords. A client generates a short-lived token with aws dsql generate-db-connect-admin-auth-token (for the admin role) or generate-db-connect-auth-token (for custom database roles mapped to IAM roles) and uses it as the password over TLS.

In the AWS Management Console

  1. Open the Aurora DSQL console and choose Create cluster, then Single-Region (or Multi-Region to pick a witness Region and a remote Region).

  2. Optionally change the Name tag, add tags, choose a customer managed KMS key, keep Enable deletion protection on (the default) and optionally add a resource-based policy.

  3. Choose Create cluster, wait for the status Active, then choose Connect with Query editor and connect as admin to run SQL, or copy the endpoint for psql.

  4. For multi-Region, complete the pending setup: create or choose the second cluster in the remote Region and choose Peer; the pairing is finished when both clusters show as peered.

With the AWS CLI

# Single-Region cluster
CLUSTER_ID=$(aws dsql create-cluster --region us-east-1 \
  --tags Key=app,Value=bookshelf --query identifier --output text)
aws dsql get-cluster --region us-east-1 --identifier "$CLUSTER_ID" --query status

HOST="$CLUSTER_ID.dsql.us-east-1.on.aws"
export PGPASSWORD=$(aws dsql generate-db-connect-admin-auth-token --region us-east-1 --hostname "$HOST")
psql "host=$HOST port=5432 dbname=postgres user=admin sslmode=verify-full sslrootcert=system"
unset PGPASSWORD

# Multi-Region: first cluster names a witness Region; create the peer in a second Region, then peer both
aws dsql create-cluster --region us-east-1 \
  --multi-region-properties '{"witnessRegion":"us-west-2"}'

Derived from Getting started with Aurora DSQL, AWS CLI Command Reference — dsql and Migrating from PostgreSQL to Aurora DSQL. Complete a multi-Region pair with the console flow above or with aws dsql update-cluster --multi-region-properties using the witnessRegion and clusters (a list of peer cluster ARNs) properties. The IAM policy for an application role is short:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ConnectAsCustomRole",
    "Effect": "Allow",
    "Action": "dsql:DbConnect",
    "Resource": "arn:aws:dsql:us-east-1:111122223333:cluster/abcdefghijklmnopqrstuvwxyz"
  }]
}

dsql:DbConnectAdmin instead grants the admin role and belongs only to operators. Map a custom database role to an IAM role inside the database (AWS IAM GRANT) rather than sharing the admin token.

Pricing model

All prices vary by Region, engine, storage configuration and over time, so this page gives the cost drivers and no figures. Always check the dated Amazon Aurora pricing and Aurora DSQL pricing pages and model a month with the AWS Pricing Calculator.

Cost driver What to know

Compute: ACU-hours (Serverless v2)

Metered per ACU-hour for the capacity each instance actually uses between its minimum and maximum, measured continuously; a paused instance costs nothing for compute. Each writer and each reader is billed separately, so a cluster costs roughly instance count times current ACUs. The minimum is your floor cost.

Compute: instance-hours (provisioned)

Hourly per instance class, per second after a short minimum; Graviton classes are cheaper per unit of performance; Reserved Instances (and database savings plans) discount steady usage.

Storage

Per GB-month of the cluster volume actually used (it shrinks when you drop data), at a higher rate under I/O-Optimized.

I/O requests

Per million read and write requests under Aurora Standard; included under I/O-Optimized.

Backups and snapshots

Backup storage up to the size of the cluster volume in the Region is included; retained backups beyond it and manual snapshots are charged per GB-month. Backtrack change records are charged.

Clones

No copy charge at creation; you pay for the clone’s own instances and for pages it changes.

Global Database and replication

Replicated write I/O per million, cross-Region data transfer, and the compute of each secondary cluster.

Data transfer and connectivity

Cross-AZ traffic between clients and instances in other zones, Region-to-Region transfer, and the public IPv4 addresses and NAT gateways the surrounding network needs. Data API calls have their own pricing in some Regions.

Extended Support

An hourly per-vCPU (or per-ACU) surcharge for engine major versions kept running after the end of standard support, which can quickly exceed the instance cost; upgrade instead.

Aurora DSQL

Billed in Distributed Processing Units for compute, plus storage; no charge when idle apart from storage, and a multi-Region cluster consumes DPUs in each Region plus witness storage.

Cost control for Bookshelf: use a minimum of 0 ACUs in dev and test; keep the production maximum honest (a runaway query then costs money but cannot scale without bound); compare Standard and I/O-Optimized after a month; set an AWS Budget (see Cost Management and Support); delete idle clones and old manual snapshots; and stop non-production provisioned clusters with aws rds stop-db-cluster (stopped for up to seven days at a time).

Limits, quotas and recent changes

  • Up to 15 Aurora Replicas plus the writer per cluster; cluster volume up to 256 TiB on recent engine versions; default quotas per Region on clusters, instances and subnet groups can be raised through Service Quotas.

  • Serverless v2: 0 to 256 ACUs per instance; the available range depends on engine and platform version.

  • Data API: result-size and execution-time limits apply (see the limitations page linked below).

  • DSQL: 3,000 modified rows per transaction, one hour connections, the quotas page is authoritative.

  • 2025-03-31: Aurora Serverless v1 reached end of life. 2025-05: Aurora DSQL generally available. Serverless v2 scale to zero (auto-pause) shipped in late 2024 and needs the engine versions in the intro. Aurora PostgreSQL and MySQL major versions leave standard support on published dates; Extended Support fees follow.

  • Older guides still show: --engine-mode serverless clusters and --scaling-configuration; Data API as a v1-only feature; a Serverless minimum of 0.5 ACUs as the floor; password rotation built from a custom Lambda instead of --manage-master-user-password; PostgreSQL 11 or 12 and Aurora MySQL 2; storage with no I/O line item. Prefer the current approach on this page.

Monitoring

Enable CloudWatch Logs exports, Enhanced Monitoring and CloudWatch Database Insights (the successor to Performance Insights, see Amazon RDS). For Aurora watch ServerlessDatabaseCapacity and ACUUtilization (Serverless v2), CPUUtilization, FreeableMemory, DatabaseConnections, AuroraReplicaLag, VolumeReadIOPs and VolumeWriteIOPs (I/O cost), AuroraVolumeBytesLeftTotal, and BufferCacheHitRatio. RDS events (for example failover, pause and resume, RDS-EVENT-0370 to 0374 for auto-pause) can be sent to SNS or EventBridge (Monitoring and Observability). Slow-query diagnosis in PostgreSQL itself is on Diagnosing and Fixing Slow Queries.

Troubleshooting

Symptom Likely cause Check and fix

Connection times out

Security group, subnet routing, or the client is outside the VPC; the instance is public-false.

Confirm the inbound rule from the app security group on 5432/3306, the DB subnet group, and use Session Manager port forwarding. aws ec2 describe-security-groups; Reachability Analyzer.

First connection after quiet period fails or takes 15 s or more

Auto-pause resume (minimum capacity 0).

Raise client connect timeout above 30 seconds, add retries, or set a minimum of 0.5 ACUs.

Instance never pauses

Open connection, RDS Proxy, Global Database, logical replication or binlog, zero-ETL, provisioned instance in the cluster, or a tier 0 or 1 reader awake.

Read the instance log about auto-pause; check DatabaseConnections; drop the proxy or set a nonzero minimum.

FATAL: PAM authentication failed or Access denied with IAM

Expired token (15 minutes), user lacks rds_iam, wrong resource ID in the rds-db:connect ARN, IAM authentication not enabled on the cluster, TLS off.

Generate a fresh token right before connecting, GRANT rds_iam, use the cluster resource ID, enable with aws rds modify-db-cluster --enable-iam-database-authentication.

too many connections or connection storms

max_connections derives from the maximum ACU; many Lambda or ECS tasks each opening pools.

Raise the maximum ACU, shrink pools, use RDS Proxy or the Data API.

Capacity stuck at the maximum, slow queries

Range too small or an unindexed or runaway query.

Raise the maximum, inspect pg_stat_statements, add indexes (Diagnosing and Fixing Slow Queries), add readers.

Replica lag grows

Write-heavy workload, long-running reader queries, reader smaller than writer (tier 2-15 reader at low ACUs).

Move the reader to tier 0 or 1, raise capacity, shorten reader queries.

Slow after failover

Cold buffer cache on the promoted reader, clients still using stale DNS.

Use cluster endpoints and the AWS Advanced JDBC Wrapper; keep a minimum ACU that fits the working set.

InvalidParameterCombination on create-db-cluster or modify-db-cluster

Engine version does not support the feature (MinCapacity 0, I/O-Optimized, Data API, Limitless).

describe-db-engine-versions for the flag; upgrade the engine.

Data API BadRequestException or AccessDenied

Data API not enabled, missing secret permission, wrong secret or database, response too large.

enable-http-endpoint, check IAM and the secret ARN, page results with LIMIT.

DSQL OC000 or serialization failure

Optimistic concurrency conflict between transactions.

Retry the transaction with backoff; shrink transactions; spread keys.

Storage grows or I/O bill jumps

Bloat, large temp-heavy queries, many readers scanning, snapshots retained.

Check VolumeBytesUsed and I/O metrics, vacuum and drop unused data (space is released), evaluate I/O-Optimized.

Clean up

Delete in dependency order. Deletion protection must be turned off first, and the console and CLI both offer a final snapshot, which keeps data (and keeps billing) until you delete that snapshot too.

# Aurora clusters: instances first, then the cluster
aws rds modify-db-cluster --db-cluster-identifier bookshelf-catalog --no-deletion-protection --apply-immediately
for I in bookshelf-catalog-reports bookshelf-catalog-2 bookshelf-catalog-1; do
  aws rds delete-db-instance --db-instance-identifier "$I"
done
aws rds delete-db-cluster --db-cluster-identifier bookshelf-catalog --skip-final-snapshot   # or --final-db-snapshot-identifier

# Clone, restored cluster and the custom endpoint
aws rds delete-db-cluster-endpoint --db-cluster-endpoint-identifier reports      # before deleting its cluster
aws rds delete-db-instance --db-instance-identifier bookshelf-catalog-clone-1
aws rds delete-db-cluster --db-cluster-identifier bookshelf-catalog-clone --skip-final-snapshot

# Global Database: remove the secondary, then the global cluster
aws rds remove-from-global-cluster --global-cluster-identifier bookshelf-global \
  --db-cluster-identifier arn:aws:rds:us-west-2:111122223333:cluster:bookshelf-catalog-usw2 --region us-east-1
aws rds delete-global-cluster --global-cluster-identifier bookshelf-global

# Manual snapshots, subnet group and security group
aws rds delete-db-cluster-snapshot --db-cluster-snapshot-identifier bookshelf-catalog-pre-migration
aws rds delete-db-subnet-group --db-subnet-group-name bookshelf-db-subnets
aws ec2 delete-security-group --group-id "$DB_SG"

# Aurora DSQL: turn off deletion protection, then delete
aws dsql update-cluster --region us-east-1 --identifier "$CLUSTER_ID" --no-deletion-protection-enabled
aws dsql delete-cluster --region us-east-1 --identifier "$CLUSTER_ID"

Derived from aws rds delete-db-cluster, aws rds delete-global-cluster and aws dsql delete-cluster. In the console: RDS → Databases → select each instance → Actions → Delete (readers first), then the cluster; delete snapshots under Snapshots; remove the subnet group under Subnet groups; and delete DSQL clusters in the DSQL console. The RDS-managed master secret is deleted with the cluster; a customer managed KMS key you created for it is not, and is scheduled for deletion on the KMS page (see Secrets Manager, Parameter Store and KMS). In a Global Database delete the secondary clusters' instances and clusters in their own Region as well.