Course outline

7.3

Amazon Aurora Inside Out

Six copies in three AZs, quorum writes, endpoints, replica auto scaling, Serverless, Global Database, cloning, backtrack, ML and Babelfish.

32 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain what makes Aurora different from RDS for MySQL or PostgreSQL: separate compute and storage, a shared cluster volume, 6 copies in 3 AZs, quorum writes (4 of 6) and reads (3 of 6), and self-healing.
  • Describe an Aurora DB cluster: one writer, up to 15 Aurora Replicas, failover priority tiers, failover in about 30 seconds and replica lag under about 100 ms.
  • Choose the right endpoint (cluster, reader, instance, custom) and explain why the connection string never changes during an Aurora failover, while a promoted RDS read replica needs a new one.
  • Configure replica auto scaling and Aurora Serverless v2 (ACUs, minimum and maximum, scaling to 0 with auto-pause) and say when each fits.
  • Design multi-Region reads and disaster recovery with Aurora Global Database, and tell switchover from failover.
  • Pick between backups, point-in-time restore, Backtrack and cloning for a given recovery or testing need, and know Aurora machine learning, Babelfish, I/O-Optimized and zero-ETL.
  • Recognise every exam pattern that points to Aurora.

#Why Aurora exists

Lesson 7.1 showed RDS: AWS runs a normal database engine (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server, Db2) on an EC2 instance with EBS volumes, and handles patching, backups and failover for you. That engine was designed decades ago for one server with local disks, and RDS inherits its limits: a standby or replica needs its own full copy of the data, replicas replay the primary’s log and fall behind, and storage is an EBS volume you size.

Amazon Aurora is AWS’s own relational database engine, built for the cloud. Key facts:

  • Proprietary (not open source), but compatible with MySQL and PostgreSQL: your drivers, tools and most SQL work unchanged, as if Aurora were MySQL or PostgreSQL. You choose Aurora MySQL or Aurora PostgreSQL when you create the cluster.
  • It is managed through RDS (same console, same aws rds commands), but its storage is completely different.
  • Performance: AWS markets it as up to 5× the throughput of MySQL and 3× of PostgreSQL on the same hardware. Treat these as AWS’s marketing figures, measured on AWS’s benchmarks; real gains depend on your workload. For the exam, “high performance MySQL/PostgreSQL-compatible” means Aurora.
  • Cost: roughly 20% more per instance-hour than the same RDS instance, but you get the storage replication, faster failover and more replicas without paying for extra copies.
RDS for MySQL / PostgreSQLAurora MySQL / PostgreSQL
StorageEBS volumes per instance, you choose the size (storage auto scaling can grow it)One shared cluster volume, grows and shrinks automatically, pay for what you use
Copies of the data1 per instance (Multi-AZ adds a standby with its own copy)6 copies across 3 AZs, whatever the number of instances
Read replicasUp to 15 (asynchronous, each with its own storage)Up to 15 Aurora Replicas on the same storage
Replica lagSeconds or more under loadUsually under 100 ms
FailoverMulti-AZ standby: 60–120 s; read replica: manual promoteAutomatic to a replica, typically under 30 s
BackupsDaily snapshot plus logs every 5 minutes, can be disabled (retention 0)Continuous, always on, 1–35 days

#The storage layer: six copies in three AZs

#Compute and storage are separate

An Aurora cluster has two layers:

  • Compute: DB instances (a writer and readers). They run the database engine, keep a cache in memory and process SQL. They hold no permanent data.
  • Storage: the cluster volume, a distributed, SSD-based volume spread over hundreds of storage nodes in 3 Availability Zones. All instances of the cluster read and write the same volume.

Because the data does not live on the instances, adding a reader copies nothing, deleting an instance deletes no data, and failing over just means another instance takes the writer role on the same volume.

#Segments, six copies and the quorum

The cluster volume is cut into 10 GiB segments. Each segment is stored 6 times: 2 copies in each of 3 AZs (a group of 6 copies is called a protection group). The writer does not send whole data pages to storage; it sends only the redo log records (the description of each change), and the storage nodes build the pages themselves. Much less data crosses the network.

Aurora uses a quorum to decide when an operation counts:

  • A write is durable when 4 of the 6 copies confirm it. The writer sends to all 6 and continues as soon as the fastest 4 answer, so one slow disk never slows the database.
  • A read needs 3 of the 6 copies (in practice the writer knows which copies are current and reads from one; the quorum matters for recovery).
  • Because 4 + 3 = 7 is more than 6, any read quorum overlaps the last write quorum: at least one of the 3 copies has the newest data.

What survives:

Copies lostHealthyWrites (need 4)Reads (need 3)Example
06YesYesNormal
15YesYesOne disk fails
24YesYesA whole AZ fails
33NoYesAn AZ plus one more copy
42NoNoVery unlikely: 4 independent failures

So Aurora keeps writing after losing an entire AZ, and keeps your data readable (and repairable) after losing an AZ plus one more copy.

#Self-healing

Storage nodes continuously check their copies and exchange missing pieces with their peers (peer-to-peer gossip). When a copy is lost, Aurora rebuilds it on another storage node from the surviving copies. A segment is only 10 GiB, so a repair takes seconds; that keeps the window in which a second failure could hurt very small. You never see any of this: there is no RAID to manage and no volume to replace.

Six copies, three AZs, one quorum

The writer and two readers sit on top of one shared cluster volume. Every segment of that volume is stored 6 times, 2 copies per AZ. A write needs 4 copies to confirm, a read needs 3.

Scenario

us-east-1
AZ a
AZ b
AZ c
App
Writer
Reader 1
Reader 2
c1
c2
c3
c4
c5
c6
update
Step 1 of 4
1

The app sends an update to the writer. Only the writer accepts writes; the readers serve select queries. All three instances use the same storage, so adding a reader copies no data.

Now try it yourself: break copies and AZs and see when writes and reads stop.

Storage quorum lab

Every 10 GiB segment of an Aurora cluster volume is stored as 6 copies, 2 in each of 3 AZs. Click a copy or an AZ to break it, then send a write or a read. A write needs 4 of the 6 copies to confirm; a read needs 3.

Try:

AZ a

AZ b

AZ c

Healthy copies: 6/6Writes (4/6): availableReads (3/6): available

All 6 copies are healthy. Send a write: the writer sends it to all 6 and waits for the first 4 confirmations.

#Storage grows (and shrinks) by itself

  • The cluster volume grows automatically as data is added; you never provision storage or IOPS. The maximum is 128 TiB, or 256 TiB on recent engine versions (Aurora MySQL 3.10 and higher, Aurora PostgreSQL 15.13, 16.9, 17.5 and higher).
  • When you drop tables or delete data, recent versions shrink the billed size again (dynamic resizing).
  • You pay for the storage you actually use, once, not per copy: the 6 copies are included.

The slides’ phrase “grows in increments of 10 GB up to 256 TB” describes the 10 GiB segments; the notes’ “10 GB to 128 TB” was the long-standing limit. For the exam, remember “automatically grows, up to 128 TiB” (256 TiB on new versions).

Self-checkQuestion

An Aurora cluster’s storage loses both copies in AZ a and one copy in AZ b. What can the database still do?

#The Aurora DB cluster

An Aurora DB cluster is the cluster volume plus the DB instances that use it:

  • One writer (primary) instance: the only one that accepts writes (INSERT, UPDATE, DELETE, schema changes). It also serves reads.
  • Up to 15 Aurora Replicas (readers): read-only instances on the same volume, spread across AZs. They serve SELECT queries and are the failover targets.
  • Optionally, readers can be serverless (next sections) or provisioned, in any mix.

#Replica lag

An RDS read replica replays the primary’s log on its own copy of the data, so it can fall seconds or minutes behind. An Aurora Replica reads the same storage; the writer only tells it which cached pages changed. Replica lag is therefore typically under 100 ms (the slides say “sub 10 ms”; AWS documents “usually much less than 100 ms”). Watch it with the CloudWatch metric AuroraReplicaLag.

#Failover and priority tiers

If the writer fails (instance crash, AZ outage, or you trigger a failover), Aurora automatically promotes a reader to writer:

  1. It picks the reader with the highest priority: each reader has a promotion tier from 0 (highest) to 15 (lowest).
  2. Among readers in the same tier, it picks the largest instance; if they are the same size, any of them.
  3. The cluster endpoint is repointed to the new writer (next section).

There is nothing to copy or catch up, so failover typically completes in under 30 seconds, much faster than an RDS Multi-AZ standby (60–120 s). The slides call it “instantaneous” and the notes say “milliseconds”: both overstate it. Applications still see dropped connections and must reconnect; the AWS Advanced JDBC/Python/Go wrappers and RDS Proxy (lesson 7.4) shorten the pause to seconds.

With no readers at all, Aurora creates a new writer instance in the same or another AZ. Your data is safe (it is in the 3-AZ storage), but this takes about 10 minutes. For high availability, always run at least one reader in another AZ.

Tip for tiers: give the reader that should take over a low tier (0 or 1) and the same size as the writer. Give analytics or reporting readers higher tiers (2–15) so they are not promoted.

#Endpoints: the names your app connects to

Aurora gives you DNS names (endpoints) instead of instance addresses. Each endpoint is a CNAME that Aurora keeps pointing at the right instances.

EndpointExample namePoints toUse it for
Cluster endpoint (writer endpoint)mycluster.cluster-c1a2b3.us-east-1.rds.amazonaws.comThe current writer, always, also after failoverAll writes, and reads that must see the latest data
Reader endpointmycluster.cluster-ro-c1a2b3.us-east-1.rds.amazonaws.comAll readers, load-balanced per connectionRead-only traffic. With no readers, it points to the writer
Instance endpointmycluster-instance-2.c1a2b3.us-east-1.rds.amazonaws.comOne specific instanceDiagnosis, or very special tuning. Avoid in apps: it does not move on failover
Custom endpointreports.cluster-custom-c1a2b3.us-east-1.rds.amazonaws.comA subset of instances you chooseIsolating a workload, for example analytics on larger instances. Up to 5 per cluster by default

Two details that trip people up:

  • The reader endpoint balances connections, not queries. DNS hands out a different reader to each new connection; all queries on one connection go to the same reader. An app with one long-lived connection gets no spread. Use a connection pool.
  • The reader endpoint includes every reader. Once you define custom endpoints for special instances, connect normal traffic to a custom endpoint of the normal readers too, otherwise customer queries may land on the analytics instance. (AWS: “the reader endpoint is generally not used after defining custom endpoints”.)

Aurora endpoints and failover

The app knows two DNS names: the cluster (writer) endpoint for writes and the reader endpoint for reads. An analytics team uses a custom endpoint. Watch the names stay the same while the instances behind them change.

Scenario

Aurora DB cluster
App
Cluster endpointwriter
Reader endpointcluster-ro
Writertier 1
Reader 1tier 0
Reader 2tier 1
insert
Step 1 of 3
1

Writes go to the cluster endpoint (mycluster.cluster-c1a2b3.us-east-1.rds.amazonaws.com). It is a DNS CNAME that always points at the current writer.

#“Don’t change the connection string during failover”: what it really means

A classic exam question: “How can an application separate read and write traffic without changing connection strings constantly during failover?” The answer is the cluster endpoint for writes and the reader endpoint for reads. The owner’s natural confusion: “It says don’t change the connection string, but then tells me to use two different endpoints. How is that possible?”

The key words are “during failover”. You set the two names once, when you build the app. The question is about what happens afterwards, when a database fails.

  1. Initial setup, done once

    The app’s configuration file gets two connection strings: writes → mycluster.cluster-12345.us-east-1.rds.amazonaws.com, reads → mycluster.cluster-ro-12345.us-east-1.rds.amazonaws.com. That is a normal part of building the app.

  2. Plain RDS with a read replica: the problem

    The primary dies. A read replica is not promoted automatically, so you promote it by hand. The promoted replica becomes a separate, standalone database with its own endpoint (mydb-replica…), different from the old primary’s (mydb…). The app still points to the dead name: someone must edit the configuration, put in the new URL and restart or redeploy the app. That is “changing the connection string during failover”: manual, slow, and downtime while it happens.

  3. Aurora: the same failure

    The cluster has a writer and two replicas. The writer crashes. Aurora automatically promotes one replica (by tier). Then it updates the DNS record behind the cluster endpoint so the same name now resolves to the new writer.

  4. The result

    The app reconnects with exactly the same name and reaches the new writer, usually within 30 seconds. Nobody edits a file or restarts anything. The reader endpoint likewise keeps pointing at whatever readers exist.

In one line for the exam: set the cluster endpoint (writes) and reader endpoint (reads) once; during failover they move automatically behind the scenes, so the connection strings never need updating. (RDS Multi-AZ also keeps one endpoint during failover, because the standby takes over the same name; but a Multi-AZ standby instance serves no reads. Lesson 7.1 covers that.)

Why the connection string never changes

The same failure, twice: once with RDS and a read replica you promote by hand, once with an Aurora cluster endpoint.

Scenario

Appconfig file
You
DNS
Primary
Replica
mydb.abc123.rds.amazonaws.com
Step 1 of 5
1

The app’s config holds the primary’s own endpoint, mydb.abc123…. The read replica has a different name, mydb-replica.abc123….

#Replica auto scaling

Aurora Auto Scaling adds and removes Aurora Replicas automatically, using Application Auto Scaling:

  • A target tracking policy on a metric: average CPU of the readers (RDSReaderAverageCPUUtilization) or average connections to the readers (RDSReaderAverageDatabaseConnections). Example: keep average reader CPU at 60%.
  • A minimum and maximum number of replicas (maximum up to 15).
  • New replicas attach to the shared volume (no data copy), join the reader endpoint automatically, and are removed when the load falls (after a cooldown). They take several minutes to start, so they help with sustained growth more than sudden 30-second spikes.
  • Replicas you add by hand are never removed by the policy, and auto scaling is not supported on the secondary clusters of a Global Database.

If you need instant, fine-grained scaling, combine this with Serverless v2 readers.

#Aurora Serverless v2

With provisioned instances you choose an instance class (db.r6g.large, …) and pay for it every hour, busy or idle. With Aurora Serverless v2 you choose a capacity range and Aurora sizes the instance for you, second by second.

  • Capacity is measured in ACUs (Aurora capacity units): 1 ACU ≈ 2 GiB of memory with matching CPU and networking.
  • You set a minimum and maximum for the cluster: from 0 (or 0.5) up to 256 ACUs (384 on recent Aurora PostgreSQL versions). Every serverless instance scales independently inside that range.
  • It scales in place, in seconds, in steps as small as 0.5 ACU, without failover and without dropping connections. It never exceeds your maximum.
  • You pay per second for the ACUs used (ACU-hours), plus storage and I/O as usual.
  • Scale to zero (auto-pause), since late 2024: set the minimum to 0 ACUs and an instance with no user connections for a chosen time (SecondsUntilAutoPause, default 300 seconds, up to 1 day) pauses. Compute costs nothing while paused; storage is still billed. The next connection resumes it in about 15 seconds (30 seconds or more after more than 24 hours paused), so clients need connection timeouts and retries. Open connections, RDS Proxy, binlog or logical replication, zero-ETL integrations and being a Global Database cluster all prevent pausing.
  • Mixed clusters: a cluster can contain both serverless (db.serverless) and provisioned instances, for example a big provisioned writer with serverless readers, or a serverless writer with steady provisioned readers.
  • Serverless readers in tier 0 or 1 follow the writer’s capacity (so they are ready to take over); readers in tiers 2–15 scale independently.
  • It has all Aurora features: Multi-AZ readers, Global Database, RDS Proxy, Backtrack, cloning.

Aurora Serverless v1 (the original, which could pause to 0 but scaled slowly and had no readers) reached end of life on 31 March 2025; remaining v1 clusters were moved to v2. The slides’ diagram with a “proxy fleet” is v1’s architecture. When the exam says “Aurora Serverless”, think v2.

When to use it:

  • Infrequent, intermittent or unpredictable workloads: a new app with unknown traffic, a site with promotions, a reporting database used at month-end.
  • Dev and test databases idle at night and on weekends (with auto-pause).
  • Many small databases (one per tenant) that are mostly idle.
  • Not ideal for a steady, predictable 24×7 load: provisioned instances with Reserved Instances are usually cheaper there.

Aurora Serverless v2: capacity follows the load

Bars show the capacity (ACUs) of one serverless instance over time; dots show the load. Pick a scenario and press play.

Scenario

Capacity range 0.5–16 ACUs. A flash sale arrives, peaks above the maximum, then fades.

max 16min 0.5ACU116131616104.51.51
Step 1 of 4
1

A quiet morning: the instance runs at 1 ACU (about 2 GiB of memory with matching CPU and network). You pay per second for the ACUs actually used, not for a fixed instance size.

#Aurora Global Database

Multi-AZ protects you inside one Region. For a Region-wide outage, or for users on other continents, Aurora has two cross-Region options.

Aurora Global Database (recommended):

  • 1 primary Region (read/write) and up to 10 secondary Regions (read-only). The notes say 5; AWS raised it to 10, as the slides show.
  • Replication happens in the storage layer, over dedicated AWS infrastructure, with lag typically under 1 second, and almost no load on the primary’s database engine.
  • Each secondary cluster can have up to 16 read-only instances (one more than the normal 15, because there is no writer). Local reads get local latency.
  • Write forwarding: a secondary cluster can accept writes from the app and forward them to the primary for you, so an app in a secondary Region can use one local endpoint. Writes still pay the cross-Region round trip.
  • A global writer endpoint always points to the current primary cluster, even after it moves Region.

Moving the primary:

Switchover (formerly “managed planned failover”)Failover (unplanned)
WhenPlanned: Region rotation, DR drills, both Regions healthyThe primary Region has an outage
Data lossNone: waits until the secondary is fully syncedWhatever had not replicated yet (RPO of seconds, typically under 1 s)
DowntimeShortRTO typically under 1 minute
AfterRoles swapped, topology keptOld primary rejoins as a secondary when it recovers

For Aurora PostgreSQL you can set a managed RPO: the primary refuses commits if no secondary is within that many seconds, which caps how much data a failover can lose.

Aurora cross-Region read replicas (the older way, Aurora MySQL with binlog replication) also give a copy in another Region, are simple to set up and help with DR, but replication goes through the database engine (slower, more lag, load on the writer) and promotion is manual and slower. Prefer Global Database.

Aurora Global Database

A primary cluster in us-east-1 takes all writes. A secondary cluster in eu-west-1 gets a copy through storage-level replication and serves local reads.

Scenario

us-east-1 (primary)
eu-west-1 (secondary)
American users
Writer
Cluster volume
European users
Reader
Cluster volume
insert
Step 1 of 4
1

An American user writes. The writer in the primary Region commits to its local 6-copy volume as usual.

#Aurora machine learning

Usually, to add a prediction to an app you export data, send it to an ML service and write the results back. Aurora machine learning lets you call AWS ML services directly from SQL:

  • Amazon SageMaker AI: any model you trained and deployed (fraud detection, product recommendations, ad targeting).
  • Amazon Comprehend: ready-made natural language processing, for example sentiment of a review (positive, negative, neutral), with no model to train.
  • Amazon Bedrock (newer): foundation models, for example to summarise text or create embeddings from SQL.

You need no ML experience: an IAM role lets the cluster call the service, and you use SQL functions, for example in Aurora PostgreSQL:

SELECT review_id,
       (aws_comprehend.detect_sentiment(review_text, 'en')).sentiment
FROM product_reviews
WHERE created_at > now() - interval '1 day';

Use cases from the slides and notes: fraud detection, ads targeting, sentiment analysis, product recommendations (“which products should this customer see?”).

#Babelfish for Aurora PostgreSQL

Many companies run apps on Microsoft SQL Server, whose SQL dialect is T-SQL, and whose apps talk the SQL Server wire protocol with SQL Server drivers. Moving to PostgreSQL normally means rewriting queries, stored procedures and drivers.

Babelfish is a feature of Aurora PostgreSQL that understands T-SQL and the SQL Server protocol. Turn it on, and:

  • The app keeps its SQL Server client driver and connects to Babelfish’s SQL Server port (1433); Babelfish translates T-SQL into PostgreSQL behind the scenes. The app thinks it is talking to SQL Server.
  • Few or no code changes. Some T-SQL features are not supported; the Babelfish Compass tool reports what will need changes.
  • The same database also accepts normal PostgreSQL connections, so you can modernise piece by piece.
  • Migrate the schema and data with AWS SCT and AWS DMS (or Babelfish’s own tools), then point the app at Aurora.

#Backups and restores

#Automated backups

  • Aurora backs the cluster volume up continuously and incrementally to S3, with no performance impact and no backup window freeze (RDS for MySQL takes a daily snapshot that can cause a brief I/O pause on Single-AZ).
  • Automated backups are always on: retention 1 to 35 days, cannot be disabled (RDS allows 0 to disable).
  • Point-in-time recovery (PITR) to any second in the retention period, typically up to about 5 minutes ago.
  • Backup storage up to the size of your cluster volume is free for the retention period.

#Manual snapshots

  • Triggered by you (or AWS Backup), kept as long as you want, even after the cluster is deleted.
  • Can be copied to other Regions and shared with other accounts.
  • For retention longer than 35 days (1, 3, 7 years for compliance), use AWS Backup plans; lesson 7.2 explains this for RDS and it works the same for Aurora.

#Restore options

  • Restoring a backup or snapshot always creates a new cluster with new endpoints. The existing cluster is untouched. You then add instances to the new cluster.
  • Restore from S3 (Aurora MySQL): to migrate an on-premises MySQL database, take a physical backup with Percona XtraBackup, upload the files to S3, and create a new Aurora MySQL cluster from them. Faster than a logical dump for large databases. (Plain RDS for MySQL can also be restored from an XtraBackup in S3.)
  • Other migration paths: a logical dump (mysqldump, pg_dump), AWS DMS, or creating an Aurora read replica of an RDS for MySQL/PostgreSQL instance and promoting it.

#Backtrack: rewind in place (Aurora MySQL)

A restore creates a new cluster, which takes time and gives you a new endpoint to switch to. Backtrack instead rewinds the existing cluster to an earlier moment, like turning back a clock:

  • No new cluster, same endpoints, done in minutes, to the second (Aurora picks the nearest consistent point).
  • You can move back and forth to find the exact moment before the mistake (back 3 hours, forward 1 hour…).
  • The backtrack window is at most 72 hours. Aurora keeps change records for your target window and you pay per hour for them; under heavy write load the actual window can be shorter.
  • Aurora MySQL only, not Aurora PostgreSQL.
  • Must be enabled when you create the cluster (or restore a snapshot into a new one); you cannot turn it on for an existing cluster.
  • It rewinds the whole cluster, not one table: everything written after that moment is undone too.
  • It causes a brief disruption: stop the app, Aurora closes connections, rewinds, reopens.
  • Not supported with Global Database, and not with cross-Region read replicas (forcing it breaks binlog replicas).

It is not a backup. It protects against human error in the last hours, not against losing the cluster.

#Cloning: instant test copies

Aurora cloning creates a new cluster from an existing one using the copy-on-write protocol:

  • At first the clone shares the same storage pages as the source; nothing is copied. A clone of a multi-terabyte database is ready in minutes and costs almost nothing extra in storage at first.
  • When either side changes a page, only that page is copied and stored separately; each side is billed for the pages it changed.
  • The source is not slowed down, and the clone can use different instance sizes, serverless, or a single instance.
  • Up to 15 copy-on-write clones per source; after that a clone is a full copy. Same Region only (can be another VPC or, via AWS RAM, another account).

Compared with snapshot and restore: a restore copies all data back from S3 (slow for big databases, full storage cost), while a clone is near-instant and shares storage. Compared with a read replica: a replica is read-only and part of production; a clone is an independent, writable cluster.

#A dropped table at 14:05: which tool?

ToolWhere the data comes backHow longEndpointRewinds everything else?Engines
BacktrackSame cluster, in placeMinutesSameYes, the whole clusterAurora MySQL, if enabled at creation
Point-in-time restoreNew clusterTens of minutes to hours, grows with sizeNewNo: copy the table backAll
Snapshot restoreNew cluster, at the snapshot’s timeLike PITRNewNoAll
CloneNew cluster, nowMinutesNewNo; it copies the present, so it does not undo a mistake, it is for testingAll

A table was dropped at 14:05

Someone ran drop table orders on production at 14:05. Three Aurora tools can bring the data back, and a fourth makes test copies. Compare where the data lands, how long it takes and whether the endpoint changes.

Scenario

App
ProductionAurora MySQLorders gone
Backupscontinuous
drop table
Step 1 of 3
1

14:05, drop table orders. The cluster was created with Backtrack enabled and a 24-hour target window, so Aurora kept change records.

#Pricing notes and newer features

#Aurora Standard vs Aurora I/O-Optimized

Two storage configurations, chosen per cluster:

  • Aurora Standard: instance hours + storage + a charge per million I/O requests. Cheapest for moderate I/O.
  • Aurora I/O-Optimized (2023): higher instance and storage prices, no I/O charges. AWS’s rule: worth it when I/O is 25% or more of your Aurora bill. Predictable costs for I/O-heavy apps.
  • You can switch from Standard to I/O-Optimized once every 30 days, and back at any time.

#Zero-ETL integration with Redshift

A zero-ETL integration replicates Aurora data into Amazon Redshift near real time, so analysts query fresh data in the warehouse without building ETL pipelines. Exam clue: “analytics on Aurora data in Redshift without ETL pipelines”.

#Side note: Aurora DSQL (2025)

Aurora DSQL is a separate serverless, distributed, PostgreSQL-compatible database (generally available since May 2025) with no instances and active-active writes in multiple Regions. It is not a feature of a normal Aurora cluster and is not yet on the SAA exam; there, “multi-Region relational DR” still means Global Database.

#Also good to know

  • Aurora supports IAM database authentication, encryption at rest with KMS (chosen at creation) and TLS in flight, the same way as RDS (lesson 7.4).
  • You can stop a cluster for up to 7 days (it restarts automatically), paying only for storage.
  • Automated patching with zero-downtime patching for most minor updates, Performance Insights and Enhanced Monitoring are built in.

#What goes wrong

  • No readers, then the writer fails: Aurora must launch a new instance (about 10 minutes). Always keep a reader in another AZ, sized like the writer, in tier 0 or 1.
  • The app uses instance endpoints: failover moves the writer and the app keeps writing to an instance that is now a reader (“read-only” errors). Use the cluster endpoint.
  • Clients cache DNS too long (Java’s default can cache forever): after failover they keep hitting the old writer. Set a short DNS TTL in the client (for example 5 seconds) or use AWS drivers / RDS Proxy.
  • Reads that must see their own writes go to the reader endpoint and miss the last 50 ms of changes. Send read-after-write queries to the cluster endpoint.
  • Reader endpoint not balancing: the app keeps one connection open. Use a pool, or reconnect periodically.
  • The failover target is too small: a tiny reader in tier 0 becomes the writer and buckles under the load. Match sizes.
  • Serverless maximum too low: queries slow at peak because capacity is capped. Watch ACUUtilization near 100%.
  • Auto-pause surprises: the first request after a pause times out (resume about 15 s), or scheduled jobs (pg_cron, MySQL events) do not run while paused.
  • Backtrack expected on PostgreSQL, or on a cluster created without it: not available. Plan PITR.
  • Global Database failover without a plan: DNS, app config and the RPO were never tested. Run switchover drills.
  • I/O bill shock on a write-heavy app on Aurora Standard: check whether I/O-Optimized is cheaper.

#Aurora in system design

  • Default choice for a relational OLTP database on AWS when you need high availability and read scaling: one writer, two or more readers in different AZs, cluster endpoint for writes, reader (or custom) endpoints for reads, RDS Proxy in front if you have many short-lived connections (Lambda).
  • Read-heavy apps: up to 15 readers with auto scaling, plus a cache (ElastiCache, lesson 7.5) for hot data.
  • Spiky or unknown traffic, dev/test, SaaS with many tenants: Serverless v2, with auto-pause for idle databases.
  • Multi-Region: Global Database for DR (RTO under a minute, RPO about a second) and local reads; write forwarding for the occasional remote write.
  • Operations: clones for testing and analytics experiments, Backtrack (MySQL) for human error, AWS Backup for long retention, zero-ETL to Redshift for analytics.
  • When not Aurora: Oracle, SQL Server or Db2 without Babelfish (use RDS), a small cheap database with steady low load (RDS Single-AZ can be cheaper), or key-value access at massive scale (DynamoDB).

#Try it yourself

# 1. Create an Aurora PostgreSQL cluster (the volume) with a serverless range, then a writer and a reader
aws rds create-db-cluster --db-cluster-identifier shop \
  --engine aurora-postgresql --engine-version 16.9 \
  --master-username dbadmin --manage-master-user-password \
  --serverless-v2-scaling-configuration MinCapacity=0,MaxCapacity=16,SecondsUntilAutoPause=600 \
  --storage-type aurora-iopt1 \
  --db-subnet-group-name db-private --vpc-security-group-ids sg-0abc1234def567890

aws rds create-db-instance --db-instance-identifier shop-writer \
  --db-cluster-identifier shop --engine aurora-postgresql --db-instance-class db.r7g.large
aws rds create-db-instance --db-instance-identifier shop-reader-1 \
  --db-cluster-identifier shop --engine aurora-postgresql --db-instance-class db.serverless \
  --promotion-tier 1 --availability-zone us-east-1b

# 2. See the cluster endpoint, the reader endpoint and who is the writer
aws rds describe-db-clusters --db-cluster-identifier shop \
  --query "DBClusters[0].[Endpoint,ReaderEndpoint,DBClusterMembers[].[DBInstanceIdentifier,IsClusterWriter,PromotionTier]]"

# 3. Watch the endpoint move: resolve it, fail over, resolve again (same name, new address)
dig +short shop.cluster-c1a2b3.us-east-1.rds.amazonaws.com
aws rds failover-db-cluster --db-cluster-identifier shop --target-db-instance-identifier shop-reader-1
dig +short shop.cluster-c1a2b3.us-east-1.rds.amazonaws.com

# 4. A custom endpoint for analytics instances
aws rds create-db-cluster-endpoint --db-cluster-identifier shop \
  --db-cluster-endpoint-identifier reports --endpoint-type READER \
  --static-members shop-analytics-1

# 5. Replica auto scaling: 1 to 8 readers, keep average reader CPU at 60%
aws application-autoscaling register-scalable-target --service-namespace rds \
  --resource-id cluster:shop --scalable-dimension rds:cluster:ReadReplicaCount \
  --min-capacity 1 --max-capacity 8
aws application-autoscaling put-scaling-policy --service-namespace rds \
  --resource-id cluster:shop --scalable-dimension rds:cluster:ReadReplicaCount \
  --policy-name reader-cpu-60 --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration \
  '{"TargetValue":60,"PredefinedMetricSpecification":{"PredefinedMetricType":"RDSReaderAverageCPUUtilization"}}'

# 6. Clone production for testing (copy-on-write), then give it an instance
aws rds restore-db-cluster-to-point-in-time --source-db-cluster-identifier shop \
  --db-cluster-identifier shop-test --restore-type copy-on-write --use-latest-restorable-time

# 7. Point-in-time restore to 14:04:59 (always a NEW cluster)
aws rds restore-db-cluster-to-point-in-time --source-db-cluster-identifier shop \
  --db-cluster-identifier shop-1404 --restore-to-time 2026-10-25T14:04:59Z

# 8. Backtrack an Aurora MySQL cluster (created with --backtrack-window 86400) in place
aws rds backtrack-db-cluster --db-cluster-identifier shop-mysql \
  --backtrack-to 2026-10-25T14:04:59Z
aws rds describe-db-cluster-backtracks --db-cluster-identifier shop-mysql

# 9. Global Database: wrap the cluster, add a secondary Region, later switch over
aws rds create-global-cluster --global-cluster-identifier shop-global \
  --source-db-cluster-identifier arn:aws:rds:us-east-1:111122223333:cluster:shop
aws rds create-db-cluster --region eu-west-1 --db-cluster-identifier shop-eu \
  --engine aurora-postgresql --engine-version 16.9 --global-cluster-identifier shop-global
aws rds switchover-global-cluster --global-cluster-identifier shop-global \
  --target-db-cluster-identifier arn:aws:rds:eu-west-1:111122223333:cluster:shop-eu

# 10. Watch replica lag and serverless capacity
aws cloudwatch get-metric-statistics --namespace AWS/RDS --metric-name AuroraReplicaLag \
  --dimensions Name=DBInstanceIdentifier,Value=shop-reader-1 \
  --start-time 2026-10-25T13:00:00Z --end-time 2026-10-25T14:00:00Z --period 300 --statistics Maximum

#Summary

Key takeaways

  • Aurora is AWS’s own MySQL- and PostgreSQL-compatible engine: separate compute and storage, marketed at up to 5× MySQL and 3× PostgreSQL throughput, about 20% more than RDS per instance.
  • The cluster volume is split into 10 GiB segments, each stored 6 times across 3 AZs. Writes need 4 of 6, reads 3 of 6: it keeps writing after losing an AZ, and keeps data readable after an AZ plus one copy. It is self-healing and grows automatically to 128 TiB (256 TiB on new versions).
  • A cluster has one writer and up to 15 Aurora Replicas on the same storage: replica lag under about 100 ms, automatic failover by promotion tier (0–15), typically under 30 s. Without readers, recovery takes about 10 minutes.
  • Endpoints: cluster (always the writer), reader (load-balanced per connection), instance (one instance, avoid in apps), custom (a subset, for example analytics). Set them once; on failover the DNS moves behind the same name, so connection strings never change. A promoted RDS read replica gets a new endpoint.
  • Replica auto scaling: target tracking on reader CPU or connections, between a min and max.
  • Serverless v2: capacity in ACUs (about 2 GiB each), min to max (0–256), scales in place in seconds, pay per second; min 0 = auto-pause, resume about 15 s. For infrequent, intermittent, unpredictable loads. Can mix with provisioned. v1 retired in 2025.
  • Global Database: 1 primary + up to 10 secondary Regions, storage replication under 1 s, 16 readers per secondary, write forwarding; switchover (planned, no data loss) vs failover (outage, RTO under 1 minute, RPO seconds).
  • Aurora ML calls SageMaker, Comprehend or Bedrock from SQL. Babelfish lets Aurora PostgreSQL understand T-SQL for SQL Server apps with few changes.
  • Backups are continuous, always on, 1–35 days, no performance impact; PITR and snapshot restores create a new cluster; on-premises MySQL migrates via Percona XtraBackup in S3.
  • Backtrack (Aurora MySQL, up to 72 h, enabled at creation) rewinds the whole cluster in place, same endpoint. Cloning (copy-on-write) makes fast, cheap test copies; prefer it over snapshot restore for staging.
  • I/O-Optimized when I/O is 25% or more of the bill; zero-ETL feeds Redshift; Aurora DSQL (2025) is a separate multi-Region active-active product.