Skip to content
Aurora
Sub-page 1 of 8
Core one-way-door · Free

Choosing MySQL- or PostgreSQL-Compatibility Before Backtrack and Autovacuum Make the Choice for You

Decision drivers
  • 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.