Aurora
Choosing MySQL- or PostgreSQL-Compatibility Before Backtrack and Autovacuum Make the Choice for You
- Which engine (MySQL or PostgreSQL) the team already runs and has tooling/expertise for
- Whether the workload includes long-running analytics/reporting queries against read replicas
- Whether the recovery plan assumes Backtrack (MySQL-only)
- Dependence on any PostgreSQL extension not on Aurora's supported list
Production premise
This mostly isn't a decision made on Aurora's own merits — match your team's
existing engine and tooling. But one specific mechanism is worth knowing
before you assume parity: Aurora PostgreSQL doesn't run vanilla vacuum
behavior unmodified. Adaptive autovacuum (rds.adaptive_autovacuum, on by
default) automatically makes autovacuum more aggressive as a table's
transaction age approaches autovacuum_freeze_max_age, which vanilla
PostgreSQL doesn't do on its own.
Failure mode & inflection point
Adaptive autovacuum helps with wraparound risk, but it doesn't touch a
separate, Aurora-specific trap. Because Aurora replicas share the writer's
storage layer rather than replaying their own physical copy, a long-running
read query on a replica directly affects what the writer's vacuum process
is allowed to clean up — that's the mechanism, not just a side effect.
AWS's own documentation states hot_standby_feedback is on by default and
unmodifiable in Aurora PostgreSQL (unlike standard RDS PostgreSQL, where
it's a real toggle) — so unlike vanilla Postgres, you can't choose to trade
it off. A long-running analytics query left open on a reader can quietly
stall vacuum on the writer, and MaximumUsedTransactionIDs climbing toward
autovacuum_freeze_max_age while vacuum appears to be running is the tell
that a reader replica, not the writer's own workload, is the actual
blocker. Separately, on the MySQL-compatible side: Backtrack (a fast
in-place rewind tool, see page 7) simply doesn't exist on
Postgres — a recovery runbook that assumes it does is a bad time to find
out.
Production guardrail
Default to PostgreSQL for a genuinely new build with no existing stack to
match — it's had the more actively-developed feature surface on Aurora
specifically, a broader extension ecosystem (including pgvector for
anything touching embeddings/AI workloads), and stricter type/constraint
enforcement that catches mistakes MySQL would silently accept. Move to
MySQL instead when a specific, named factor points there: the team already
runs MySQL-compatible tooling, ORMs, or a CMS platform with a hard MySQL
dependency (WordPress, Drupal, and similar); the workload specifically
needs Backtrack's fast in-place rewind (MySQL-only — see page
7) and standard PITR/snapshot restore isn't fast enough; or the
team's existing depth is specifically in MySQL, deep enough that a
Postgres switch costs more in ramp-up than it buys in features.
If you land on Postgres, one operational trap is worth planning for
immediately: watch MaximumUsedTransactionIDs against your
autovacuum_freeze_max_age setting, and if it's climbing, check for
long-running or idle-in-transaction sessions on reader replicas before
assuming the writer's autovacuum configuration is the problem. Because you
can't turn hot_standby_feedback off here, the actual fix is capping how
long analytics/reporting queries are allowed to run on replicas — not
adjusting vacuum settings on the writer. Verify any specific PostgreSQL
extension your team depends on against Aurora's supported list before
migration planning, since Aurora PostgreSQL has historically lagged
vanilla Postgres on newer extension support.