Citus
A PostgreSQL extension that shards tables across a cluster of ordinary Postgres servers, sending each query to the one shard it needs or to all shards in parallel.
- What it is
- Relational databases
- Part of
- Built on PostgreSQL
- Type
- Open source
- Made by
- Microsoft (Citus Data)
- License
- AGPL-3.0
- Facts checked
- 24 October 2026
What it is
Citus is loaded into every server of a cluster with shared_preload_libraries = 'citus' and CREATE EXTENSION citus. One server is the coordinator, which applications connect to; the others are workers, added with citus_add_node. Calling create_distributed_table('campaigns', 'company_id') splits a table into shards, 32 by default (citus.shard_count), each covering a range of hash values of the distribution column. A shard is just a regular Postgres table on a worker, such as campaigns_102027, and metadata tables like pg_dist_shard, pg_dist_placement and pg_dist_node record where each one lives. A query that filters on the distribution column is routed whole to one worker; any other query is rewritten into one fragment per shard, run on the workers in parallel and combined on the coordinator. Tables distributed on the same column are colocated, so their matching rows sit on the same node and joins and foreign keys between them stay local. Small lookup tables become reference tables, with a full copy on every node. Since Citus 11.0 (2022) the metadata is synchronised to every node, so any node can run distributed queries, though DDL still goes through the coordinator. Since 12.0 (2023) there is a second model, schema-based sharding: every table in a distributed schema lives whole on one node, which suits apps that already keep one schema per tenant or per microservice. Shards move between nodes with logical replication, so adding a node and rebalancing doesn’t block writes; this needs a primary key on every table. A columnar table access method stores append-mostly data compressed by column.
Citus Data was founded in 2011 and bought by Microsoft in January 2019; the extension is AGPL-3.0, and since 11.0 every feature, including the non-blocking rebalancer, is in the open-source release. It supports the latest three Postgres major versions: 14.0 (February 2026) added PostgreSQL 18 and dropped 15, and 14.3 shipped on 23 October 2026. The managed versions are on Azure only. Azure Cosmos DB for PostgreSQL, which ran Citus, is on a retirement path: new deployments are blocked and Microsoft has set its retirement for 31 March 2029. Microsoft points users to elastic clusters in Azure Database for PostgreSQL flexible server, which run Citus 14 with PostgreSQL 18 since September 2026. Self-hosted, Citus has no failover of its own: each node is an ordinary Postgres server, and Patroni 3.0 and later can manage a whole Citus cluster.
Why teams pick it
- An extension, not a fork: the nodes run stock PostgreSQL, so Postgres drivers, tools and other extensions keep working, and new Postgres versions are supported soon after release
- Fits multi-tenant SaaS well: distribute every table by tenant, and each tenant’s queries and transactions run on one node with full SQL, while a large tenant can be isolated on a node of its own
- Spreads scans and aggregates over all shards in parallel, for dashboards on live data; Citus cites Heap with 1.4 PB on a 100-node cluster
- Starts as a single node and grows: add workers and rebalance shards online, all in the open-source release
Watch out for
- The distribution column shapes the schema: primary keys and unique constraints must include it, foreign keys between distributed tables must include it, and reference tables can’t have foreign keys to distributed tables
- Not every query spans shards: correlated subqueries and outer joins work across shards only on the distribution column, and recursive CTEs, grouping sets and
SELECT … FOR UPDATEonly within one shard - No built-in high availability when self-hosted: every coordinator and worker needs its own replicas and failover, usually through Patroni
- AGPL-3.0, and managed only on Azure, where Cosmos DB for PostgreSQL users must move to elastic clusters before 31 March 2029
Good for
- SQL past one serverShards tables across ordinary Postgres workers by a distribution column, sends single-tenant queries to one node and fans the rest out.
- Sub-second queries on fresh eventsScans and aggregates run on all shards in parallel, for dashboards on live data; Citus cites 1.4 PB on a 100-node cluster.
- Data model
- Relational; tables sharded by a distribution column, plus reference tables copied to every node
- Query language
- PostgreSQL SQL, with limits on some queries across shards
- Client protocol
- PostgreSQL wire protocol
- How it scales
- Hash shards (32 by default) by distribution column, or one schema per node; online rebalancing
- Replication
- None of its own: each node is a Postgres server with its own replicas, often run by Patroni
- Storage engine
- Stock PostgreSQL tables; a
columnaraccess method for append-mostly data - Ways to run it
- Self-hosted extension, or elastic clusters in Azure Database for PostgreSQL
More of the PostgreSQL family
What all relational databases have in common →Compare side by side →
OmnigresDormantOpen sourceBuilt on itA set of more than 30 Postgres extensions that turn one Postgres instance into an application server: it answers HTTP, runs Python, loads code from files and sends email, all inside the database’s transactions.How it fits with other technologies
What Citus uses
Colocated tables sharded by company, a reference table, and an online rebalance · sql
-- on every node: shared_preload_libraries = 'citus' in postgresql.conf
CREATE EXTENSION citus;
-- on the coordinator: register the cluster
SELECT citus_set_coordinator_host('coord', 5432);
SELECT citus_add_node('worker-1', 5432);
SELECT citus_add_node('worker-2', 5432);
CREATE TABLE companies (id bigint PRIMARY KEY, name text);
CREATE TABLE campaigns (company_id bigint, id bigint, name text,
PRIMARY KEY (company_id, id)); -- must include the distribution column
CREATE TABLE countries (code char(2) PRIMARY KEY, name text);
SELECT create_distributed_table('companies', 'id');
SELECT create_distributed_table('campaigns', 'company_id', colocate_with => 'companies');
SELECT create_reference_table('countries'); -- a full copy on every node
-- routed to one worker: the filter names the distribution column
SELECT count(*) FROM campaigns WHERE company_id = 42;
-- one fragment per shard, run in parallel, merged on the coordinator
SELECT company_id, count(*) FROM campaigns GROUP BY company_id ORDER BY 2 DESC LIMIT 10;
-- after adding a worker: move shards with logical replication, writes keep flowing
SELECT citus_rebalance_start();Row-based or schema-based sharding?#
Citus 12.0 added a second way to split data. Both can run in the same cluster.
| Row-based | Schema-based | |
|---|---|---|
| Set up with | create_distributed_table on each table, naming its distribution column | citus.enable_schema_based_sharding, then ordinary CREATE SCHEMA |
| Schema changes | Every table needs the tenant column, and keys must include it | None: each table in the schema becomes a single-shard table |
| Joins and foreign keys | Between colocated tables on the distribution column, and to reference tables | Within one schema, and to reference tables |
| Queries across tenants | Run in parallel over all shards | Not parallelised |
| Tenants it suits | About 100 to over a million | About 1 to 10 thousand |
See it in a real stack
No architecture uses Citus yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from2011–2026
PostgreSQL runs on one machine, so applications that outgrew it either sharded by hand in application code or moved to a NoSQL store and gave up SQL. Umur Cubukcu, Ozgun Erdogan and Sumedh Pathak, who met at graduate school at Stanford, founded Citus Data in Istanbul in January 2011 and joined Y Combinator that summer. Erdogan’s idea was a way to scale out a database without giving up transactions, joins and foreign keys. Their first database was a fork of Postgres; along the way they released cstore_fdw, a columnar store, and the pg_shard extension in 2014.
By then Postgres had become much more extensible, and in March 2016 Citus 5.0 was rebuilt entirely on its extension APIs and released as open source, which the company called the first distributed database that doesn’t fork the underlying database. A managed Citus Cloud followed in July 2016. Microsoft bought Citus Data in January 2019 and ran Citus on Azure, in the service now called Azure Cosmos DB for PostgreSQL and later in elastic clusters for Azure Database for PostgreSQL.
Citus 11.0 in June 2022 open-sourced the remaining enterprise features and let any node run distributed queries. Citus 12.0 in July 2023 added schema-based sharding for apps built around a schema per tenant, and Citus 14.0 in February 2026 brought PostgreSQL 18 support.
Why it’s built this way
- Extend Postgres instead of forking it
- A fork has to be merged with every Postgres release. Moving to the extension APIs meant users get new Postgres features immediately and keep their existing drivers and tools.
- Shards are plain Postgres tables
- Each shard is a regular table on a worker, so the workers’ own Postgres planner, indexes and storage do the local work, and Citus only has to plan across shards.
- Colocate related tables by a shared distribution column
- Placing the shards that hold related rows of related tables on the same node lets joins, foreign keys and transactions for one tenant run on one machine without cross-node coordination.
- A second model with one schema per shard
- Many multi-tenant apps already keep each tenant in its own schema and can’t add a tenant column to every table. Schema-based sharding scales them out with no query changes, at the cost of fewer tenants per node and no parallel cross-tenant queries.
Timeline
- 2011
Citus Data is founded in Istanbul and joins Y Combinator
- 2014
cstore_fdwcolumnar store and thepg_shardextension are released - 2016
Citus 5.0 becomes a Postgres extension and goes open source; Citus Cloud launches
- 2019
Microsoft acquires Citus Data
- 2022
Citus 11.0 goes fully open source and lets any node run distributed queries
- 2023
Citus 12.0 adds schema-based sharding
- 2026
Citus 14.0 supports PostgreSQL 18; Azure sets Cosmos DB for PostgreSQL to retire in 2029
- Citus Data: Our story (founders, timeline)
- Citus blog: Citus unforks from PostgreSQL, goes open source (Mar 2016)
- Microsoft blog: Microsoft acquires Citus Data (Jan 2019)
- Citus blog: Citus 11 for Postgres goes fully open source, with query from any node (Jun 2022)
- Citus blog: Citus 12, schema-based sharding for PostgreSQL (Jul 2023)
- Citus blog: Distribute PostgreSQL 18 with Citus 14 (Feb 2026)
Sources18 · facts checked 24 October 2026
- citusdata/citus on GitHub: README (AGPL-3.0, architecture, install, Patroni support)
- citusdata/citus: release v14.3.0 (23 Oct 2026)
- Citus docs: Concepts (coordinator, workers, shards, colocation, reference tables)
- Citus docs: What is Citus? (use cases, scale, when not to use it)
- Citus docs: Creating and modifying distributed objects (constraints, foreign keys)
- Citus docs: SQL support and workarounds
- Citus docs: Configuration reference (citus.shard_count defaults to 32)
- Citus docs: Citus utility functions
- Citus docs: Table management (columnar storage)
- Citus updates: v14.0 (PostgreSQL 18, PostgreSQL 15 dropped, latest three majors)
- Citus blog: Citus 11 for Postgres goes fully open source (non-blocking rebalancer)
- Citus updates: v11.0 (tenant isolation, non-blocking rebalancer needs primary keys)
- Citus blog: Citus 12, schema-based sharding for PostgreSQL
- Microsoft Learn: Elastic clusters in Azure Database for PostgreSQL flexible server
- Microsoft Learn: Azure Cosmos DB for PostgreSQL overview (on a retirement path)
- Microsoft Learn: Migrate Azure Cosmos DB for PostgreSQL to elastic clusters (new deployments blocked)
- Azure update AZ556085: Azure Cosmos DB for PostgreSQL will retire on 31 March 2029 (Mar 2026, message-center mirror)
- Azure update AZ571047: PG18 support for elastic clusters is generally available (Sep 2026, message-center mirror)