The PostgreSQL Cluster
In PostgreSQL, the word "cluster" does not mean a group of networked machines the way it does almost everywhere else in database vocabulary.
It means the single running server instance, and everything that instance owns: its data directory, its shared memory, its roles, and every database created inside it.
Summary
- Core Idea: A PostgreSQL cluster is the one server instance created by
initdb, holding all the databases, roles, and shared memory that instance manages together. - Why It Matters: Config, restarts, upgrades, and connection limits apply at the cluster level, not the database level, so understanding cluster scope prevents wrong assumptions about isolation.
- Key Concepts: cluster, PGDATA, postmaster, template database, tablespace, role.
- When to Use: Deciding whether a new app gets its own database inside an existing cluster or a cluster of its own, reasoning about
max_connectionsas a shared budget, or planning multi-tenant isolation. - Limitations / Trade-offs: Sharing a cluster means sharing failure blast radius, version upgrades, and connection capacity across every database inside it.
- Related Topics: roles and privileges, connection pooling, multi-tenant patterns, backup and restore scope.
Foundations
Every PostgreSQL server starts life with a single command: initdb.
That command creates a directory on disk, conventionally called PGDATA, and everything the server instance will ever manage lives inside it.
This PGDATA directory, plus the running postmaster process that serves it, is what the word "cluster" refers to in PostgreSQL.
A useful analogy is an office building: the cluster is the building itself, databases are the floors, schemas are the rooms on each floor, and tables are the filing cabinets inside each room.
One building has one lobby, one set of elevators, and one security desk, no matter how many floors it has.
In the same way, one cluster has one postmaster process, one shared memory region, and one set of roles, no matter how many databases live inside it.
CREATE DATABASE does not start a new server process or allocate a separate chunk of shared memory.
It copies a template database (template1 by default) into a new database entry inside the same running instance.
That single, shared instance is also why the term is confusing at first: it has nothing to do with high-availability clustering, replica sets, or Patroni-managed failover groups, which are a completely different, higher-level concept built on top of individual clusters.
Mechanics & Interactions
A single postgresql.conf file governs the entire cluster, so settings like shared_buffers and max_connections are cluster-wide budgets, not per-database allowances.
ALTER DATABASE ... SET and ALTER ROLE ... SET let you override specific settings for one database or role, but they layer on top of the cluster-wide defaults rather than replacing the shared instance underneath them.
Roles are the sharpest example of this shared scope, because a role created in one database is visible and usable from every database in the cluster, even though its object-level privileges are typically granted per database.
A backend process connects to exactly one database at a time, and there is no built-in cross-database JOIN; reaching into another database in the same cluster requires dblink or a foreign data wrapper, treating it almost like a remote server.
-- Cluster-wide facts vs per-database facts
SHOW data_directory; -- one path, whole cluster
SELECT datname FROM pg_database; -- every database this cluster owns
SELECT rolname FROM pg_roles; -- roles are visible cluster-wideTablespaces let you place individual databases, tables, or indexes on different physical disks while staying inside the same logical cluster, which is a storage-layout decision rather than an isolation decision.
WAL (write-ahead log) is generated as a single, cluster-wide stream, which is exactly why replication and point-in-time recovery are configured once per cluster rather than once per database.
Because the WAL stream and the shared buffer pool are both cluster-wide, a spike of write activity in one database directly competes for the same I/O and memory budget as every other database on that instance.
Advanced Considerations & Applications
Major-version upgrades operate on the whole cluster at once, since pg_upgrade migrates every database in PGDATA together and there is no way to run PostgreSQL 17 for one database and PostgreSQL 18 for another inside the same instance.
That single-version constraint is a real planning input for multi-tenant systems, because it means every tenant sharing a cluster is forced onto the same upgrade schedule whether or not they are ready for it.
max_connections is the sharpest shared-resource constraint in practice, since it is set once for the whole cluster and every database, every role, and every application competes for the same pool of backend slots, which is exactly why connection pooling matters even on a lightly loaded cluster.
Backup granularity follows the same split as everything else: pg_basebackup captures the entire cluster as a physical unit, while pg_dump can target a single database for a logical, more selective backup.
Security boundaries need the same correction, because a role's login credentials work across every database in the cluster even though GRANT statements scope its actual privileges per object, so "different database" is not the same guarantee as "different login."
| Isolation approach | Strength | Weakness | Best Fit |
|---|---|---|---|
| Schema-per-tenant, one database | Cheapest; single connection pool; easy cross-tenant reporting | Weakest isolation; one bad query affects everyone | Small teams, low tenant count, trusted tenants |
| Database-per-tenant, one cluster | Stronger isolation; per-database backup/restore | Still shares max_connections, shared buffers, and version upgrades | Mid-size SaaS wanting isolation without new infrastructure |
| Cluster-per-tenant | Full resource and version isolation | Highest operational cost; more instances to patch and monitor | Regulated or high-value tenants needing hard isolation |
Common Misconceptions
- "A cluster means multiple servers working together." The term predates and has nothing to do with high-availability clustering; it is simply the name for one
initdb-created instance, however confusing that overlap with modern HA vocabulary feels. - "Roles belong to a single database." Roles are created and visible cluster-wide; only the privileges granted to a role are scoped per database or per object.
- "Different databases in a cluster can run different PostgreSQL versions." One binary and one running
postmasterserve every database inPGDATA, so the whole cluster upgrades together viapg_upgrade. - "Restarting the server only affects the database I'm working in." A restart stops and starts the entire
postmasterprocess, which takes down every database in the cluster at once. - "More databases always means more isolation, so it's always the safer choice." Extra databases still share
max_connections, shared buffers, and WAL throughput, so isolation gains come with real, shared-resource trade-offs.
FAQs
What exactly does "cluster" mean in PostgreSQL, if it's not multiple servers?
It refers to one server instance and its data directory (PGDATA), created by a single initdb call, along with every database and role that instance manages.
How is a cluster different from a database?
A cluster is the whole running instance; a database is one of potentially many logical containers inside that instance, each with its own tables and schemas but sharing the cluster's roles and resources.
Do all databases in a cluster share the same PostgreSQL version?
Yes, always - one binary serves the entire cluster, so a major-version upgrade via pg_upgrade moves every database in that cluster together.
Are roles shared across every database in a cluster?
Yes - a role created in one database is visible and can log in from any database in the same cluster, even though its actual privileges are granted per database or per object.
Can I query across two databases in the same cluster with a normal JOIN?
No - a backend connects to one database at a time, so cross-database access requires dblink or a foreign data wrapper rather than a native JOIN.
Does `max_connections` apply per database or per cluster?
Per cluster - it is one shared budget of backend connection slots that every database and every application competes for, which is a major reason connection pooling matters.
What is a template database and why does `CREATE DATABASE` need one?
CREATE DATABASE works by copying an existing template database, template1 by default, into a new entry inside the same cluster rather than starting a new server process.
If I restart the server, does it only affect the database I'm connected to?
No - a restart stops and starts the single postmaster process for the whole cluster, so every database on that instance goes down and comes back up together.
What's the difference between a tablespace and a database?
A tablespace is a storage-location decision, letting you place data on a different disk; a database is a logical isolation boundary for tables and schemas, and either can use any tablespace in the cluster.
When should I use database-per-tenant instead of schema-per-tenant?
Reach for database-per-tenant when you need stronger isolation and per-tenant backup and restore, and can accept that tenants still share the cluster's connection limit and version upgrade schedule.
When does it make sense to give a tenant their own cluster entirely?
When regulatory requirements or blast-radius concerns demand full resource and version isolation, since a separate cluster is the only option that removes shared max_connections, shared buffers, and upgrade timing entirely.
Is "cluster" in PostgreSQL related to tools like Patroni?
Not directly - Patroni manages high-availability failover between PostgreSQL clusters (a primary and its replicas), while "cluster" itself just describes one of those individual instances.
Related
- Installation Basics - installing the binaries that create your first cluster
- initdb & Data Directory - what
initdbactually creates on disk - postgresql.conf Essentials - the cluster-wide config file this page assumes
- Roles Basics - why roles are cluster-wide, not per-database
- Database, Schema & Search Path - the object hierarchy inside one database
Stack versions: This page was written for PostgreSQL 18.4 (stable 18, maintenance line 17).