Deploy Citus | (Just Updated) Distributed Postgres 17, Extension Enabled, Data Survives Redeploys

Citus distributed PostgreSQL 17, extension on, generated password

Deploy Citus | (Just Updated) Distributed Postgres 17, Extension Enabled, Data Survives Redeploys

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 (host RAILWAY_TCP_PROXY_DOMAIN, port RAILWAY_TCP_PROXY_PORT).
  • Private URL: postgresql://postgres:@citus.railway.internal:5432/railway, exposed as DATABASE_PRIVATE_URL.
  • Credentials: user postgres, password in POSTGRES_PASSWORD, database railway.
  • 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" returning accepting connections, or a successful psql "$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_table works immediately, with no CREATE EXTENSION and 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

Implementation Details

VariablePurpose
POSTGRES_PASSWORDPassword of the postgres user, generated per deploy.
DATABASE_PRIVATE_URLConnection string on the private network, for services in the same project.
DATABASE_URLConnection string on the TCP proxy, for clients outside Railway.

Template Content

More templates in this category

View Template
RustFS | (Just Updated) S3 Object Store, Public URL and Keys Set
S3-compatible object store, keys and public URL preset, volume kept

SuperSlowSloth
0
View Template
TimescaleDB
A PostgreSQL-based time-series database for analytics on Railway.

Rakit
1
View Template
Garage S3 Storage
Ultra-light S3 server: fast, open-source, plug-and-play.

PROJETOS
8