Can You Run Citus on Amazon RDS for PostgreSQL? A Reality Check
If an Amazon RDS for PostgreSQL architecture depends on running CREATE EXTENSION citus, stop before estimating nodes, shards, or throughput. Citus is not in the current RDS extension matrix, and an RDS administrator cannot install the missing native package.
Situation
RetailCo’s order platform began on one PostgreSQL database. Years later, its transaction history is 40 TB, checkout writes compete with operational queries, and the largest RDS instance no longer provides comfortable peak headroom.
Most orders are tenant-local. An order, its items, payment state, and shipment belong to one tenant_id. That makes Citus attractive: distribute tenant rows across workers, colocate related tables, and let several PostgreSQL servers own different writes.
The platform team also has a firm managed-service requirement. Its first proposed architecture tries to combine both preferences:
flowchart TD
App[RetailCo applications] --> Coordinator[RDS PostgreSQL coordinator]
Coordinator --> WorkerA[RDS PostgreSQL worker A]
Coordinator --> WorkerB[RDS PostgreSQL worker B]
Coordinator --> WorkerC[RDS PostgreSQL worker C]
Extension[Citus extension] --> Coordinator
Extension --> WorkerA
Extension --> WorkerB
Extension --> WorkerC
The diagram looks plausible. Each node is PostgreSQL. RDS supports PostgreSQL extensions. The database owner receives an rds_superuser role. AWS even supports extensions such as pg_partman, pglogical, and postgres_fdw on applicable engine versions.
But the proposed architecture fails at its first prerequisite.
As of this article’s March 31, 2026 documentation cutoff, AWS’s RDS for PostgreSQL extension matrix does not list Citus. AWS instructs customers to use SHOW rds.extensions to see the extensions supported by a specific engine version. If an extension is not supplied for that engine, granting another database role does not make its files appear on the server.
The Problem
The misunderstanding begins with the word extension. PostgreSQL extensions do not all have the same deployment requirements.
Some are primarily SQL objects. Others include compiled code, server hooks, background processes, control files, and shared libraries. PostgreSQL’s own extension packaging documentation explains that CREATE EXTENSION loads objects from files already installed on the database server; extensions containing C code typically include a shared library.
Citus is in the second category. Its installation procedure installs an operating-system package and configures shared_preload_libraries = 'citus' before creating the extension. Citus then hooks into PostgreSQL’s planner and executor to coordinate distributed work: Citus 13 installation and Citus concepts.
The dependency chain is therefore:
flowchart TD
Package[Citus operating-system package] --> Files[control files and shared library]
Files --> Preload[Citus loaded at server start]
Preload --> Create[CREATE EXTENSION citus]
Create --> Metadata[distributed-table metadata]
Metadata --> Workers[coordinator routes work to workers]
RDS controls the host operating system and the PostgreSQL installation. The customer cannot add the Citus package or place its control and library files into PostgreSQL’s installation directories.
AWS is explicit about the role boundary. The initial postgres account on RDS has NOSUPERUSER and NOREPLICATION; members of rds_superuser can install extensions supported by RDS, but cannot access the host operating system or connect as PostgreSQL’s actual superuser: Understanding the rds_superuser role.
That leads to the core question:
If standard RDS cannot supply the Citus runtime, which architecture solves RetailCo’s real problem without pretending a different extension is a distributed database?
The Answer Is an Architecture Choice, Not an Extension Workaround
There is no supported SQL command, privilege grant, parameter-group setting, or trusted-extension shortcut that turns a standard RDS for PostgreSQL instance into a Citus coordinator or worker.
The preflight check should happen before any design review:
SHOW rds.extensions;
SELECT
name,
default_version,
installed_version
FROM pg_available_extensions
WHERE name IN (
'citus',
'pg_partman',
'pglogical',
'postgres_fdw'
)
ORDER BY name;
Run this on the exact RDS PostgreSQL engine and minor version under evaluation. Do not copy expected output from another version, and do not infer availability from generic PostgreSQL documentation.
The RDS parameter rds.allowed_extensions = '*' is easy to misread. AWS documents it as allowing all extensions available for the RDS engine version. It does not allow arbitrary packages from the PostgreSQL ecosystem: Restricting installation of PostgreSQL extensions.
Why pg_partman does not replace Citus
pg_partman is supported on RDS for PostgreSQL 12.5 and later. It automates the creation, retention, and maintenance of native PostgreSQL table partitions: Managing PostgreSQL partitions with pg_partman.
That can be extremely useful for a 40-TB transaction table. RetailCo could partition by month so retention, index maintenance, archival, and time-bounded queries operate on smaller physical tables.
flowchart TD
App[application writes] --> Writer[one RDS PostgreSQL writer]
Writer --> Parent[transactions parent table]
Parent --> P1[January partition]
Parent --> P2[February partition]
Parent --> P3[March partition]
Parent --> P4[future partitions managed by pg_partman]
Every partition still uses the same RDS DB instance’s compute, memory, WAL path, and writer. Partitioning can improve pruning and data lifecycle operations. It can reduce particular maintenance and query costs. It does not create independent PostgreSQL workers that concurrently own different tenants.
The distinction is structural:
| Capability | Native partitioning with pg_partman | Citus distributed tables |
|---|---|---|
| Splits one logical table | Yes | Yes |
| Automates partition lifecycle | Yes | Not its primary role |
| Places data on independent PostgreSQL workers | No | Yes |
| Routes by distribution column across workers | No | Yes |
| Adds independent write compute | No | Yes, when work is distributed and sufficiently local |
| Requires Citus on coordinator and workers | No | Yes |
pg_partman is a partition-management answer. Citus is a distributed-data and distributed-compute answer. Using one name in place of the other hides the original write ceiling.
Why postgres_fdw does not recreate Citus
postgres_fdw lets PostgreSQL access tables stored on remote PostgreSQL servers. It can support federation, migrations, administrative access, and deliberately designed remote-table workflows: PostgreSQL postgres_fdw.
It does not provide Citus’s distribution metadata, shard placement model, distributed-table DDL, colocation decisions, or rebalance operations. Building application-visible foreign tables across many RDS instances transfers routing, transaction design, topology changes, and failure handling to the architects and operators. That may be a valid custom federation design, but it should not be represented as “Citus on RDS.”
Why pglogical does not add write owners
RDS supports pglogical on applicable versions, as shown in the current extension matrix. Logical replication copies selected changes between PostgreSQL systems. Replication can support migrations, data integration, and some availability patterns; it does not automatically divide authoritative ownership of a table’s write keyspace.
If two writable databases accept conflicting updates for the same logical row, the architecture now needs ownership rules, conflict behavior, sequence and identity strategy, DDL coordination, and recovery reconciliation. Installing a replication extension does not answer those questions.
Four Valid Paths for RetailCo
Once the invalid RDS-plus-Citus premise is removed, the decision becomes much clearer.
Path 1 — Stay on one RDS database and use native partitioning
Choose this when RetailCo’s main problem is table manageability, retention, vacuum scope, index maintenance, or query pruning—and when one writer still has sufficient measured headroom.
This is the lowest-migration-risk path. It preserves standard RDS operations and PostgreSQL semantics. It should not be approved as a horizontal-write solution unless the benchmark proves the original resource ceiling was caused by work that partitioning actually removes.
Path 2 — Application-shard across multiple RDS databases
If the managed-service requirement is firm and tenant_id is a stable ownership key, RetailCo can place tenant groups on independent RDS PostgreSQL databases:
flowchart TD
Request[request with tenant identifier] --> Catalog[tenant placement catalog]
Catalog --> RdsA[RDS shard A — tenants one]
Catalog --> RdsB[RDS shard B — tenants two]
Catalog --> RdsC[RDS shard C — tenants three]
RdsA --> Pipeline[change-data pipeline]
RdsB --> Pipeline
RdsC --> Pipeline
Pipeline --> Analytics[cross-tenant reporting]
This creates real independent write capacity because each database owns different tenants. When every shard is configured with the required backup and Multi-AZ policies, RDS manages the database hosts, storage, backups, and instance failover inside each shard.
RetailCo must own the distributed control plane:
- authoritative tenant placement and request routing;
- tenant movement, validation, cutover, and rollback;
- schema rollout across every database;
- hot-tenant isolation and capacity forecasting;
- fleet-wide PITR and disaster-recovery procedures;
- cross-shard reporting and any exceptional cross-shard transaction.
This is not Citus, but it is an honest managed PostgreSQL sharding architecture.
Path 3 — Run Citus on infrastructure RetailCo controls
If Citus behavior is the requirement, the PostgreSQL hosts must permit Citus packages and configuration. On AWS, that usually means EC2 instances or another supported Citus platform rather than standard RDS for PostgreSQL.
flowchart TD
App[RetailCo applications] --> Pool[connection pool]
Pool --> Coordinator[Citus coordinator on EC2]
Coordinator --> WorkerA[worker A on EC2]
Coordinator --> WorkerB[worker B on EC2]
Coordinator --> WorkerC[worker C on EC2]
Orders[orders distributed by tenant identifier] --> WorkerA
Orders --> WorkerB
Orders --> WorkerC
Reference[small reference tables] --> WorkerA
Reference --> WorkerB
Reference --> WorkerC
Citus uses a coordinator to hold distributed metadata and plan work across workers. Distributed tables are divided into shards according to a distribution column; reference tables are copied across workers; related tables can be colocated so equal distribution-key values reach the same worker: Citus concepts and create_distributed_table.
For RetailCo, tenant_id is a stronger candidate than four-value brand_id. A high-cardinality tenant key spreads ownership more evenly and makes checkout transactions local when every related table carries that key. The decision still requires measurements for tenant skew, cross-tenant queries, global constraints, and large tenants.
The operational exchange is substantial. RetailCo now owns operating-system patching, PostgreSQL and Citus upgrades, coordinator availability, worker replication, backups, point-in-time recovery, node replacement, shard movement, monitoring, and failure testing. Citus documentation describes worker high availability using PostgreSQL streaming replication and notes that the coordinator contains essential metadata: Citus cluster management.
Path 3b — If managed Citus is the actual requirement, the offering is not on AWS
The question in this article’s title has a narrow answer for RDS, but architects should know the complete one. Managed Citus does exist: Microsoft acquired Citus Data and operates the extension as a first-party service, currently branded Azure Cosmos DB for PostgreSQL. It provides coordinator and worker nodes, create_distributed_table(), colocation, reference tables, and the rebalancer as a managed control plane rather than as packages RetailCo installs on EC2.
That reframes the decision honestly. “We want Citus without operating Citus” is not an impossible requirement — it is a requirement that selects a different cloud. For RetailCo, whose constraint is a firm AWS-managed-service preference, the relevant conclusion is that the managed-Citus option and the AWS option are mutually exclusive, and the team must decide which of the two preferences is actually binding: the extension, or the provider.
Two clarifications prevent the common follow-up mistakes:
- Aurora PostgreSQL does not change the answer. Aurora is a different storage architecture, not a more permissive extension host. Citus is absent from its supported extension list for the same reason it is absent from RDS: AWS does not ship the server-side package. “Try Aurora instead” is not a workaround.
- Aurora Limitless is not managed Citus. It solves an adjacent problem with a different implementation, table model, and compatibility surface, as the next path describes. Shared vocabulary — shards, distribution keys, colocation — does not imply a portable design.
Path 4 — Evaluate an AWS-managed distributed PostgreSQL architecture
Aurora PostgreSQL Limitless Database provides database-managed routers and shards, but it is not “Citus delivered through RDS.” It has its own table types, shard-key rules, PostgreSQL compatibility boundaries, version track, backup model, and unsupported integrations.
For RetailCo’s tenant-local workload, it is the primary AWS-managed proof-of-concept candidate. The compatibility inventory and design tradeoffs are covered in Scaling Writes in Amazon Aurora: What Actually Works?.
If neither Citus nor Limitless fits, domain decomposition remains a valid fifth direction: separate orders, payments, inventory, and history when their transaction and recovery contracts do not need one database commit.
In Practice
Context: AWS publishes an extension matrix per RDS PostgreSQL engine version and tells administrators to inspect rds.extensions. Citus is absent from the current matrix, while pg_partman, pglogical, and postgres_fdw are listed for applicable versions.
Action: Make extension availability a deployment gate. Run SHOW rds.extensions and query pg_available_extensions on the exact target version before approving any extension-dependent architecture.
Result: The design either proceeds with a supported prerequisite or fails before migration code, performance projections, and operating procedures are built on an impossible topology.
Learning: An extension name on the public internet is not evidence that a managed PostgreSQL service has installed its server-side files.
Context: AWS documents that rds_superuser is not PostgreSQL superuser and has no host operating-system access. PostgreSQL documents that native extensions require server-installed control, script, and often shared-library files.
Action: Classify every required extension by installation mechanism: SQL-only or native package, preload requirement, background workers, engine-version compatibility, and upgrade coupling.
Result: The compatibility review exposes which capabilities depend on the managed provider’s build rather than on a database grant.
Learning: Privilege and software availability are different controls.
Context: AWS describes pg_partman as automation for PostgreSQL’s native child partitions. Citus describes workers that store distributed shards and a coordinator that routes or parallelizes queries.
Action: State the resource boundary for every proposed “partitioning” solution: one writer with many child tables, or multiple workers with separate compute and ownership.
Result: The architecture review can determine whether the proposal improves lifecycle management or actually distributes write work.
Learning: Partition count is not a write-scalability metric.
Proposed verification lab — no empirical result yet
This article makes no throughput claim. A useful lab should compare the architectures using the same RetailCo schema, data distribution, durability, and transaction semantics.
| Test | One partitioned RDS database | Application-sharded RDS | Citus on EC2 |
|---|---|---|---|
| Tenant-local checkout | One writer, route to native partition | Route tenant to owning database | Route tenant to owning shard placement |
| Hot tenant | Observe local lock and CPU concentration | Isolate or move tenant | Observe worker and shard skew |
| Cross-tenant report | Scan relevant local partitions | Fan out or use analytics pipeline | Distributed query through coordinator |
| Cross-tenant transaction | Local database transaction | Application coordination required | Distributed transaction path |
| Add write capacity | Scale writer vertically | Add database and move tenants | Add worker and rebalance shards |
| Recovery | RDS snapshot and PITR | Restore one shard and reconcile catalog | Restore coordinator metadata and worker state consistently |
Record TPS, P50, P95, P99, aborts, retries, lock waits, WAL generation, CPU, storage latency, network traffic, connection count, tenant skew, rebalance time, and recovery time. Mark every result with the exact PostgreSQL, extension, instance, storage, and configuration versions.
For the 40-TB table, do not begin by copying all data. Start with a representative but explicitly labeled dataset, validate query and transaction locality, then test a staged migration with change capture, per-tenant reconciliation, cutover, and rollback. A proposed test is not a measured result.
Where It Breaks
| Architecture | Good fit | Where it breaks | Complexity owner |
|---|---|---|---|
| RDS with native partitioning | One writer still fits; lifecycle and pruning are the main problems | Writer CPU, WAL, locks, and storage path remain shared | AWS plus database team |
| Application-sharded RDS | Stable tenant key and strong managed-service requirement | Routing drift, hot tenants, fleet schema changes, cross-shard work | Application and platform teams |
| Citus on EC2 | Need Citus semantics and operational control | Coordinator and worker HA, upgrades, backups, rebalance, operational staffing | Database and infrastructure teams |
| Aurora PostgreSQL Limitless | AWS-managed horizontal writes and compatible tenant-local schema | Unsupported PostgreSQL features or integrations, poor shard key, distributed transactions | AWS plus database architecture team |
| Domain decomposition | Clear business ownership and different recovery contracts | Event delivery, reconciliation, partial workflows, duplicated data | Application and platform teams |
Several warning signs should stop the design review:
- “We have
rds_superuser, so we can install it.” The role cannot install a native package that AWS has not supplied. - “
rds.allowed_extensionsis*, so all extensions are allowed.” The wildcard covers extensions available for that RDS engine version. - “
pg_partmandistributes our partitions.” It manages native partitions inside the same PostgreSQL database and writer boundary. - “
postgres_fdwgives us transparent sharding.” It provides remote-table access; the architecture still owns placement, routing, transactions, and failure semantics. - “Logical replication gives every node write capacity.” Replication does not define conflict-free ownership of the same rows.
- “Citus will scale any workload linearly.” Cross-shard joins, multi-shard transactions, hot tenants, coordinator work, network, storage, and rebalance behavior must be measured.
The migration boundary is equally important. A live 40-TB table is not moved safely through one maintenance-window command. Regardless of target, RetailCo needs an inventory of tables and dependencies, a shard-key and transaction-locality analysis, a staged copy, ongoing change capture, reconciliation, controlled routing changes, and a rollback path.
What to Do Next
For RetailCo, do not pursue Citus on standard Amazon RDS for PostgreSQL. The prerequisite is unsupported, and pg_partman, pglogical, postgres_fdw, or extra privileges do not recreate Citus.
Because RetailCo prefers AWS-managed operations and its checkout path is predominantly tenant-local, the recommended order is:
- Verify that the current ceiling is write compute, WAL, lock contention, or storage latency—not avoidable reads or poor SQL.
- Use native partitioning and
pg_partmanfor the 40-TB table’s lifecycle and pruning needs, but do not claim that work adds independent writers. - Build an Aurora PostgreSQL Limitless compatibility proof of concept using the exact supported engine patch and
tenant_idas the candidate shard key. - Keep application-sharded RDS databases as the managed-PostgreSQL fallback when Limitless compatibility fails.
- Choose Citus on EC2 only when Citus-specific behavior is worth owning the full coordinator, worker, HA, backup, upgrade, and rebalance lifecycle.
- Move cross-tenant reporting away from the checkout commit path regardless of the selected OLTP architecture.
- Publish no scaling claim until tenant-local, hot-tenant, cross-shard, capacity-addition, and recovery tests have measured results.
Good fit: application-sharded RDS or Aurora Limitless when tenant_id is stable, high-cardinality, and present in most transactions; Citus on EC2 when operational control and Citus semantics are explicit requirements.
Poor fit: any design labeled “Citus on standard RDS PostgreSQL,” or any sharding proposal whose critical transactions do not carry a stable ownership key.
Main advantage of the recommendation: it preserves the managed-service preference without building on an unavailable extension.
Main limitation: managed horizontal write scale still requires schema, routing, transaction, migration, and recovery redesign; AWS does not remove those architectural decisions.
Operational complexity: medium for application-sharded RDS or Limitless; high for self-managed Citus.
Migration complexity: high for a live 40-TB system. Execute by tenant or another verifiable ownership slice, not as an undifferentiated table copy.
- Problem: RetailCo needs more write ownership domains, but the proposed Citus runtime is not available on standard RDS for PostgreSQL.
- Solution: separate table-management needs from distributed-compute needs, then choose native RDS partitioning, application-sharded RDS, Aurora Limitless, or self-managed Citus according to the actual boundary.
- Proof: AWS’s current extension matrix omits Citus and its role documentation denies host access; Citus’s own installation and architecture documentation requires server packages, preload configuration, a coordinator, and workers.
- Action: run the extension preflight and transaction-locality review before the next architecture meeting. If either the required runtime or a stable ownership key is missing, reject that option before benchmarking it.