Scaling Writes in Amazon Aurora: What Actually Works?
An Aurora cluster can add readers, scale its writer vertically, forward writes from replicas, and replicate across Regions—yet still send every data modification to one writer. The architecture does not scale writes until it distributes ownership of those writes.
Situation
RetailCo runs its order platform on Aurora PostgreSQL. Product queries, order history, and operational reports have already moved to reader instances. Connection pooling is in place. The busiest SQL statements have been tuned. The writer can still become the limiting resource during peak checkout because orders, line items, inventory reservations, and idempotency records all commit there.
Its transactions history has grown to 40 TB. Most customer-facing transactions include a tenant_id and remain inside one tenant. Finance, fraud, and executive reporting span tenants, but those workloads do not need to execute inside the checkout commit.
This is a reference architecture, not a claimed customer benchmark. The important facts are the transaction boundaries:
- tenant-local OLTP is the dominant write path;
- cross-tenant work is primarily analytical;
- PostgreSQL compatibility matters;
- AWS-managed operations are preferred;
- recovery and schema compatibility matter as much as throughput.
The standard Aurora topology is excellent for availability and read scale:
flowchart TD
App[RetailCo applications] --> Writer[one primary writer]
Writer --> Volume[shared Aurora cluster volume]
ReaderA[reader one] --> Volume
ReaderB[reader two] --> Volume
ReaderC[reader three] --> Volume
ReadApi[order history and catalog reads] --> ReaderA
Reports[operational reports] --> ReaderB
Failover[writer failure] --> ReaderC
AWS documents one primary instance with up to 15 Aurora Replicas. The primary performs all modifications to the cluster volume; replicas support read operations and can be promoted during failover: Adding Aurora Replicas.
That architecture answers two important questions:
- How do we keep serving reads without sending every query to the writer?
- What instance can take over if the writer fails?
It does not answer a third:
How do independent compute resources process different writes at the same time?
The Problem
Aurora offers several features with the word “scaling” or “forwarding” attached to them. They operate at different layers, and confusing those layers leads to expensive designs that leave the original bottleneck intact.
| Aurora capability | What it improves | Where writes commit |
|---|---|---|
| Larger provisioned writer | CPU, memory, and network headroom | The same writer |
| Aurora Serverless v2 | Elastic instance capacity | The writer instance |
| Aurora Replicas | Read capacity and failover targets | The writer instance |
| Local write forwarding | Connection routing from in-Region replicas | The writer instance |
| Global write forwarding | Write submission from a secondary Region | The primary Region’s writer |
| Multiple application-sharded clusters | Independent tenant or domain ownership | One writer per cluster |
| Aurora PostgreSQL Limitless Database | Database-managed routers and data shards | The owning shard or coordinated shards |
The first five choices can reduce load, simplify routing, or add elasticity. Only the last two create multiple write-ownership domains.
This is the Aurora-specific form of the single-writer ceiling: adding another place to send a request is not the same as adding another place that owns the data being changed.
Serverless v2 changes capacity, not ownership
Aurora Serverless v2 can scale a writer’s ACUs within a configured range. On supported engine versions and configurations, AWS also supports automatic pause at 0 ACUs: Aurora Serverless v2 auto-pause.
That makes Serverless v2 useful for elastic capacity and idle-cost control. It does not turn a standard cluster into a multi-writer database. One writer can become larger or smaller; it remains one writer.
Write forwarding changes the route, not the commit owner
Local write forwarding allows an application connected to an Aurora Replica to issue a supported write. Aurora forwards that write to the cluster’s writer for commit.
flowchart TD
App[application session] --> Reader[Aurora Replica]
Reader --> Read[eligible reads execute on replica]
Reader --> Forward[write is forwarded]
Forward --> Writer[cluster writer commits change]
Writer --> Storage[shared cluster volume]
Storage --> Reader
AWS currently documents local forwarding for Aurora PostgreSQL 16.4 and later 16 releases, 15.8 and later 15 releases, and 14.13 and later 14 releases: Local write forwarding in Aurora PostgreSQL. Aurora MySQL supports local forwarding on version 3.04 and later, including its 8.4-compatible versions: Local write forwarding in Aurora MySQL.
This can simplify application connections and provide read-after-write consistency modes. It can also add forwarding latency, consistency waits, SQL restrictions, and writer sessions. Aurora PostgreSQL local forwarding does not support SERIALIZABLE isolation and has restrictions involving statements, procedures, and RDS Proxy: PostgreSQL forwarding configuration and forwarding limitations.
Global write forwarding follows the same architectural rule. A secondary Region forwards the statement to the primary cluster, the primary changes the data, and the result propagates back: Aurora Global Database write forwarding.
Write forwarding is therefore a routing feature. It is not horizontal write capacity.
Four Architectures That Actually Change the Outcome
Once monitoring proves the writer is the sustained bottleneck, RetailCo has four credible paths. The right answer depends on whether the problem is temporary capacity, tenant ownership, product compatibility, or an overly broad transaction boundary.
Option 1 — Keep standard Aurora and buy headroom
The first option is deliberately conservative:
- remove reads still hitting the writer;
- remove unused or duplicate indexes;
- batch small commits where correctness permits;
- reduce lock duration and hot-row contention;
- use an appropriately sized provisioned or Serverless v2 writer;
- move analytical reads to a separate path.
This is the right answer when the projected workload still fits a larger writer with acceptable safety margin. It is also the safest first stage while a sharding migration is being designed.
It is not a long-term scale-out architecture. The maximum practical writer size, storage latency, WAL generation, lock contention, and maintenance impact remain shared constraints.
Option 2 — Shard across multiple Aurora clusters
Application sharding gives each tenant group an independent Aurora cluster:
flowchart TD
Request[request with tenant identifier] --> Catalog[tenant placement catalog]
Catalog --> ClusterA[Aurora cluster A — tenant group one]
Catalog --> ClusterB[Aurora cluster B — tenant group two]
Catalog --> ClusterC[Aurora cluster C — tenant group three]
ClusterA --> Stream[change stream]
ClusterB --> Stream
ClusterC --> Stream
Stream --> Analytics[cross-tenant analytics]
Each cluster retains familiar Aurora behavior: one writer, replicas, backups, failover, and its own blast radius. Across clusters, RetailCo now has several independent writers because each cluster owns different tenants.
This is real horizontal write scaling. It also makes RetailCo responsible for:
- the tenant placement catalog;
- request routing and cache invalidation;
- tenant movement and shard rebalancing;
- schema deployment across clusters;
- cross-shard queries and transactions;
- fleet-wide backups, PITR, and recovery testing;
- hot-tenant isolation;
- connection-pool growth across destinations.
Application sharding is often the best compatibility option when the workload needs standard Aurora PostgreSQL features that Limitless does not support. It provides control at the price of running a database fleet.
Option 3 — Use Aurora PostgreSQL Limitless Database
Aurora PostgreSQL Limitless Database replaces the standard writer-and-readers shape with a DB shard group containing routers and shards. Routers accept connections, locate data, coordinate distributed work, and return results. Shards own subsets of sharded tables and process those writes concurrently: Limitless architecture.
flowchart TD
App[RetailCo PostgreSQL clients] --> Endpoint[Limitless cluster endpoint]
Endpoint --> RouterA[router one]
Endpoint --> RouterB[router two]
RouterA --> ShardA[shard A — tenant key range]
RouterA --> ShardB[shard B — tenant key range]
RouterB --> ShardB
RouterB --> ShardC[shard C — tenant key range]
Reference[reference tables — copied to shards] --> ShardA
Reference --> ShardB
Reference --> ShardC
Limitless provides three table types:
| Table type | Placement | RetailCo use |
|---|---|---|
| Sharded | Hash-distributed by a chosen shard key | Orders, order items, tenant transactions |
| Reference | Copied to each shard | Small, infrequently changed shared lookup data |
| Standard | Stored on one system-selected shard | Small tables that do not need distributed capacity |
The standard-table detail matters. Moving a schema to Limitless without converting the growing tables to sharded tables does not distribute their write workload. Standard tables remain bounded by one shard.
For RetailCo, the core schema could make tenant_id part of every primary key and collocate the tables used by checkout:
BEGIN;
SET LOCAL rds_aurora.limitless_create_table_mode = 'sharded';
SET LOCAL rds_aurora.limitless_create_table_shard_key = '{"tenant_id"}';
CREATE TABLE orders (
tenant_id bigint NOT NULL,
order_id bigint NOT NULL,
customer_id bigint NOT NULL,
order_status text NOT NULL,
ordered_at timestamptz NOT NULL,
total_amount numeric(18,2) NOT NULL,
PRIMARY KEY (tenant_id, order_id)
);
SET LOCAL rds_aurora.limitless_create_table_collocate_with = 'orders';
CREATE TABLE order_items (
tenant_id bigint NOT NULL,
order_id bigint NOT NULL,
line_number integer NOT NULL,
product_id bigint NOT NULL,
quantity integer NOT NULL,
unit_price numeric(18,2) NOT NULL,
PRIMARY KEY (tenant_id, order_id, line_number),
FOREIGN KEY (tenant_id, order_id)
REFERENCES orders (tenant_id, order_id)
);
COMMIT;
The session variables and collocation pattern follow AWS’s documented table-creation model: Creating Limitless tables. AWS also documents that primary and unique keys on sharded tables must include the shard key. Foreign keys between sharded tables require collocation, and the foreign key must include the shard key: Limitless DDL limitations.
This is not syntactic trivia. It forces the data model to declare the ownership boundary. An email address cannot be globally unique through UNIQUE (email) on a table sharded by tenant_id; the supported unique key must include the shard key. RetailCo must decide whether uniqueness means “inside one tenant” or whether a separate globally coordinated registry is required.
Option 4 — Decompose the database write path
RetailCo may not need one database to own checkout, payments, inventory, reporting, and historical audit data.
flowchart TD
Checkout[checkout command] --> Orders[orders write domain]
Checkout --> Inventory[inventory reservation domain]
Checkout --> Payments[payment command domain]
Orders --> Outbox[durable outbox events]
Inventory --> Outbox
Payments --> Outbox
Outbox --> History[transaction history and analytics]
This path scales writes by creating domain ownership rather than tenant ownership. It is a good fit when the domains have different availability, retention, contention, and recovery needs.
The cost moves into the application: idempotency, durable events, compensation, reconciliation, and explicit state transitions. Decomposition is not a shortcut around distributed-systems work. It is a way to place that work at meaningful business boundaries instead of inside every row operation.
Limitless is managed sharding, not compatibility magic
As of this article’s March 31, 2026 documentation cutoff, AWS release notes list Aurora PostgreSQL Limitless Database 16.11-limitless, including patch 16.11.100 released February 25, 2026: Limitless release notes. Limitless uses special 16.X-limitless engine versions, so compatibility must be validated against the exact Limitless release rather than inferred from standard Aurora PostgreSQL.
That version discipline is not a formality, because the Limitless compatibility surface has moved quickly and in the direction that matters for this decision. Several restrictions that would have rejected a design at GA were lifted in later patches — advisory locks, CHECK constraints with expressions, ENUM shard keys, and pg_dump/pg_restore for migrations all arrived in 16.10.100 (February 24, 2026), and extensions including hstore, ltree, btree_gist, btree_gin, auto_explain, and pg_prewarm were added across the 16.6 through 16.11 lines. A compatibility matrix built against the 16.4 GA release will reject workloads that the current engine supports.
The correct operating rule is therefore to date the compatibility inventory and rebuild it against the exact patch the proof of concept will run, rather than to reuse a matrix from an earlier evaluation. Read the release notes forward from the version you last assessed.
AWS currently documents several boundaries that should enter the decision before a proof of concept:
- I/O-Optimized storage is required;
- shard keys cannot be updated;
SERIALIZABLEisolation is not supported;- shards cannot be merged;
- individual shards and routers cannot be deleted;
- RDS Proxy, Aurora Global Database, read replicas, AWS Backup, Blue/Green Deployments, and several other Aurora features are not supported;
- only supported PostgreSQL extensions are available;
- standard tables do not gain distributed capacity.
The full list changes as the service evolves and must be checked against Limitless requirements and considerations for the exact target release.
The backup detail is equally specific. AWS documents cluster snapshots and point-in-time recovery for Limitless. Its backup guide says not to use pg_dump, pg_dumpall, or pg_restore as the backup mechanism: Backing up and restoring Limitless. Separately, the 16.10-limitless release notes added pg_dump and pg_restore support for database migrations, including metadata preservation when moving between Limitless clusters: Limitless release notes. That migration support should not be presented as a replacement for cluster snapshots and PITR. AWS Backup being unsupported also does not mean the service has no backup capability; it means the operating workflow differs from a standard Aurora estate integrated with AWS Backup.
In Practice
Context: AWS documents a standard Aurora cluster with one primary writer and up to 15 read-only Aurora Replicas. Replicas offload SELECT traffic and can be promoted during failover: Aurora high availability.
Action: Establish the post-offload baseline: measure writer CPU, commit latency, WAL generation, storage latency, lock waits, active sessions, and the reads that still use the writer endpoint.
Result: The review can distinguish a genuine write ceiling from a routing, indexing, or connection-management problem.
Learning: Replica count is not evidence of write capacity.
Context: AWS documents that both local and global write forwarding commit changes on the writer or primary cluster. It also publishes forwarding latency, session, consistency-wait, and error metrics for Aurora PostgreSQL: Monitoring local write forwarding.
Action: Evaluate forwarding as a connection and consistency feature. Measure AuroraForwardingReplicaDMLLatency, consistency wait latency, rejected sessions, and additional writer load.
Result: The application can determine whether simpler endpoint use justifies the extra hop and compatibility boundaries.
Learning: Forwarding can simplify application routing while leaving—or increasing—writer work.
Context: AWS documents that Limitless routers coordinate queries and distributed transactions, while shards store subsets of sharded tables. Collocation sends equal shard-key values from related tables to the same shard: Limitless architecture.
Action: Test tenant-local and cross-shard workloads separately. Include a uniformly distributed tenant workload, a hot tenant, cross-tenant reporting, multi-shard transactions, shard failure, router failure, snapshot restore, and PITR.
Result: The evaluation exposes whether the application’s real transaction shape benefits from distribution or routinely pays for distributed coordination.
Learning: “Limitless” describes the service’s scaling architecture; it does not make shard-key choice or transaction locality irrelevant.
Proposed lab matrix — no empirical result yet
| Test | Standard Aurora | Application-sharded Aurora | Aurora PostgreSQL Limitless |
|---|---|---|---|
| Tenant-local checkout | Establish single-writer baseline | Route tenants across clusters | Route through Limitless endpoint with collocated tables |
| Hot tenant | Observe writer and lock concentration | Isolate or move tenant | Observe shard skew and split behavior |
| Cross-tenant transaction | Local but on one writer | Requires application coordination | Requires distributed database coordination |
| Cross-tenant report | Reader or analytical replica | Fan-out or analytical pipeline | Distributed query through routers |
| Writer or shard failure | Promote Aurora Replica | Fail over affected cluster | Exercise compute redundancy behavior |
| Recovery | Snapshot and PITR | Restore and reconcile one cluster | Restore cluster and recreate DB shard group as documented |
Record TPS, P50, P95, P99, aborts, retries, lock waits, WAL, network, storage latency, ACU utilization, router utilization, shard utilization, and recovery time. Do not compare architectures with different durability settings, datasets, or transaction semantics.
Where It Breaks
| Architecture | Good fit | Main failure mode | Complexity owner |
|---|---|---|---|
| Standard Aurora with larger writer | Workload still fits one writer with forecast headroom | Reaches the same ceiling later | DBA and cloud platform |
| Serverless v2 writer | Variable capacity within one write domain | Rapid or sustained load reaches configured or practical writer capacity | AWS plus capacity policy |
| Local or global write forwarding | Applications need simpler routing and supported consistency modes | Forwarding latency, unsupported SQL, writer session pressure | Application and DBA |
| Multiple Aurora clusters | Stable tenant key and need for standard Aurora compatibility | Routing drift, hot shards, fleet operations, tenant moves | Application and platform |
| Aurora PostgreSQL Limitless | Tenant-local PostgreSQL workload compatible with its feature set | Poor shard key, distributed transactions, unsupported integrations, one-way topology growth | AWS plus database architecture |
| Domain decomposition | Clear business consistency boundaries | Duplicate delivery, partial workflows, reconciliation gaps | Application and platform |
For RetailCo, five questions can reject an architecture quickly:
- Do most OLTP transactions include
tenant_id? If not, tenant sharding may distribute tables while leaving transactions cross-shard. - Can primary, unique, and foreign-key rules include the shard key? If not, Limitless requires a data-model redesign or a separate global registry.
- Does the platform require unsupported Limitless features? RDS Proxy, Global Database, AWS Backup integration, a particular extension, or
SERIALIZABLEcan change the answer. - Can a hot tenant be isolated or subdivided? Hash distribution helps across many keys; it does not make one key use several ownership domains automatically.
- Can cross-tenant reporting leave the OLTP path? If every report fans through transactional shards, write scale may be purchased at the expense of read and network complexity.
Migration is also a first-class constraint. Converting an existing standard table to a Limitless sharded table is synchronous and takes an ACCESS EXCLUSIVE lock according to AWS’s documented conversion procedure: Converting standard tables. That is not a credible single-step migration plan for a busy 40-TB table. The design needs staged loading, change capture or a controlled write boundary, validation by tenant, cutover, and rollback.
What to Do Next
For the RetailCo scenario, Aurora PostgreSQL Limitless Database should be the primary managed proof of concept, with multiple application-sharded Aurora clusters as the compatibility fallback.
That conclusion depends on the facts supplied by the scenario: PostgreSQL is required, most writes are tenant-local, tenant_id is present in the critical transaction path, cross-tenant reporting can move out of checkout, and managed operation is preferred.
The recommended sequence is:
- Keep the existing standard Aurora cluster stable while removing remaining avoidable writer work.
- Do not count Serverless v2 or write forwarding as horizontal write scaling; use them only for elasticity or connection-routing needs.
- Build a Limitless compatibility inventory for extensions, isolation levels, keys, foreign keys, RDS Proxy, Global Database, backup tooling, and deployment workflows.
- Create a fresh Limitless cluster on an exact
16.X-limitlesspatch and model orders and order items as collocated sharded tables usingtenant_id. - Benchmark tenant-local, hot-tenant, and cross-shard workloads separately; publish no throughput claim until raw results exist.
- Run shard, router, snapshot, and PITR failure exercises before choosing the migration architecture.
- If a required compatibility boundary fails, shard standard Aurora clusters by
tenant_idand make the tenant placement catalog a production control plane. - Keep domain decomposition available for payment, inventory, or history workloads whose transaction and recovery contracts differ from orders.
Good fit: Aurora PostgreSQL Limitless with a high-cardinality tenant key and predominantly tenant-local transactions.
Poor fit: workloads requiring routine cross-shard transactions, mutable shard keys, SERIALIZABLE, unsupported extensions, RDS Proxy, Aurora Global Database, or AWS Backup integration.
Main advantage: AWS manages routers, shards, distributed query execution, and much of the capacity layer behind one PostgreSQL-compatible endpoint.
Main limitation: the application and schema must still align with a stable shard key and the documented PostgreSQL and Aurora feature boundaries.
Operational complexity: lower than building a large application-sharded Aurora fleet, but materially higher than operating one standard Aurora cluster.
Migration complexity: high for a live 40-TB system; treat it as a tenant-by-tenant data migration with validation and rollback, not as a table-setting change.
- Problem: RetailCo’s reads scale across Aurora Replicas, but every checkout write still commits through one standard Aurora writer.
- Solution: Evaluate Limitless for database-managed tenant sharding, and retain application-sharded Aurora clusters as the fallback when compatibility requirements outweigh managed distribution.
- Proof: AWS documentation distinguishes the architectures directly: standard replicas and forwarded writes terminate at one writer, while Limitless shards store subsets of sharded tables and process writes across a DB shard group.
- Action: Produce a transaction-locality report and a compatibility matrix before provisioning the lab. If the team cannot show which writes are tenant-local and which required features Limitless lacks, it is not ready to choose the platform.