
Deploy Citus | (Just Updated) Distributed Postgres 17, Extension Enabled, Data Survives Redeploys
Citus distributed PostgreSQL 17, extension on, generated password
Just deployed
/var/lib/postgresql
Deploy and Host Citus on Railway
Built for an LLM agent to deploy and use. There is no setup step and nothing to fill in: a 32-character password is generated at deploy time, a database named railway is created, and the citus extension is already enabled in it. The contract below lists every URL, variable name and the one script that proves it works.
Citus turns PostgreSQL into a distributed database: tables are split into shards by a distribution column, and queries, inserts and joins run in parallel across them. It is used for multi-tenant SaaS back ends, real-time analytics and any workload that outgrows one Postgres table. This template runs a single-node Citus, so it is a plain PostgreSQL 17 you can already call create_distributed_table on, and the same schema can later move to a multi-node cluster.
About Hosting Citus
This template runs one service, citus, built from the official Citus 14.2.0 on PostgreSQL 17 image (citusdata/citus, pinned by digest). The image preloads the citus library and creates the extension in the railway database on first boot. In single-node mode Citus keeps all 32 shards on this node, so create_distributed_table works with no worker nodes. The data volume is mounted at /var/lib/postgresql and PGDATA stays at its default subdirectory, so the lost+found folder Railway puts at the volume root never lands inside the data directory. The start command runs as root so the root-owned volume is writable and prints the user id and mount owner in the deploy log. shared_buffers, effective_cache_size, work_mem and the worker counts are computed from the container limits, not from the host's RAM. The database port is exposed on a Railway TCP proxy; services in the same project use the private address.
Agent contract
- Public URL: none over HTTP. The database is reached on the TCP proxy as
DATABASE_URL(hostRAILWAY_TCP_PROXY_DOMAIN, portRAILWAY_TCP_PROXY_PORT). - Private URL:
postgresql://postgres:@citus.railway.internal:5432/railway, exposed asDATABASE_PRIVATE_URL. - Credentials: user
postgres, password inPOSTGRES_PASSWORD, databaserailway. - Auth: PostgreSQL password authentication (SCRAM-SHA-256) in the connection string. A wrong password is refused. The server does not offer TLS, so use the private URL for anything sensitive.
- Health: no HTTP health path (a TCP proxy and an HTTP healthcheck cannot share a service). Readiness is
pg_isready -d "$DATABASE_URL"returningaccepting connections, or a successfulpsql "$DATABASE_URL" -c 'select 1'.
# run with DATABASE_URL set; needs psql
until pg_isready -q -d "$DATABASE_URL"; do sleep 2; done
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -At <<'SQL'
select 'citus ' || extversion from pg_extension where extname = 'citus';
drop table if exists agent_events;
create table agent_events (id bigint primary key, body text);
select create_distributed_table('agent_events', 'id');
insert into agent_events select g, 'event ' || g from generate_series(1, 100) g;
select 'rows ' || count(*) from agent_events;
select 'shards ' || count(*) from citus_shards where table_name = 'agent_events'::regclass;
SQL
A fresh deploy prints citus 14.2-1, rows 100 and shards 32. Run it again and it prints the same, because the table is dropped first.
Why Deploy Citus on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Citus on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
- Agent-ready - generated password, contract block and one working script; no setup step.
- Extension on from the first boot -
create_distributed_tableworks immediately, with noCREATE EXTENSIONand no worker nodes. - One service - a single node you can deploy, pay for and redeploy, instead of a coordinator plus workers.
- State survives redeploys - the volume is mounted one level above PGDATA, so the data directory is never polluted by
lost+found. - Right-sized - Postgres memory and worker settings come from the container limits.
- Pinned image - the Citus and PostgreSQL versions are pinned, so a redeploy never changes the server underneath you.
Common Use Cases
- Multi-tenant SaaS - distribute every table by tenant id and keep one tenant's rows together.
- Real-time analytics - parallel aggregation over large event tables with plain SQL.
- A Postgres that can grow - start on one node and keep the same schema when you add workers later.
Dependencies for Citus Hosting
- One Railway volume for the data directory (created by the template).
Deployment Dependencies
- Citus documentation
- Official image
- citusdata/citus - upstream project
Implementation Details
| Variable | Purpose |
|---|---|
POSTGRES_PASSWORD | Password of the postgres user, generated per deploy. |
DATABASE_PRIVATE_URL | Connection string on the private network, for services in the same project. |
DATABASE_URL | Connection string on the TCP proxy, for clients outside Railway. |
Template Content
