Lab: Sharded Postgres (Citus)¶
Prediction checkpoint
You will run a co-located query and then one that crosses shards. Predict which query stays on one worker and which requires coordination. The distributed plan—not elapsed time alone—shows whether the shard key served the access pattern.
Pairs with: Sharding
A real Citus cluster — 1 coordinator + 3 workers. Distribute a table by shard key, query pg_dist_shard_placement to see where data actually landed, compare a cross-shard query plan against a single-shard one, and reproduce a real hot shard with docker stats showing one container doing all the work.
docker-compose.yml¶
name: labs-sharding
services:
coordinator:
image: citusdata/citus:12.1
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: app_pass
POSTGRES_DB: appdb
ports:
- "5432:5432"
healthcheck:
test: ["CMD", "pg_isready", "-U", "appuser"]
interval: 5s
timeout: 5s
retries: 20
worker1:
image: citusdata/citus:12.1
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: app_pass
POSTGRES_DB: appdb
healthcheck:
test: ["CMD", "pg_isready", "-U", "appuser"]
interval: 5s
timeout: 5s
retries: 20
worker2:
image: citusdata/citus:12.1
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: app_pass
POSTGRES_DB: appdb
healthcheck:
test: ["CMD", "pg_isready", "-U", "appuser"]
interval: 5s
timeout: 5s
retries: 20
worker3:
image: citusdata/citus:12.1
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: app_pass
POSTGRES_DB: appdb
healthcheck:
test: ["CMD", "pg_isready", "-U", "appuser"]
interval: 5s
timeout: 5s
retries: 20
# Runs once: waits for coordinator + all workers, then wires the cluster
# together with SELECT citus_add_node(...). This is the "shard count"
# control from the sim brought to life — add/remove services below and
# re-run this to change the cluster shape.
cluster-init:
image: citusdata/citus:12.1
depends_on:
coordinator:
condition: service_healthy
worker1:
condition: service_healthy
worker2:
condition: service_healthy
worker3:
condition: service_healthy
entrypoint: ["bash", "-c"]
command:
- |
set -e
for w in worker1 worker2 worker3; do
psql -h coordinator -U appuser -d appdb -c "SELECT citus_add_node('$$w', 5432);"
done
psql -h coordinator -U appuser -d appdb -c "SELECT * FROM citus_get_active_worker_nodes();"
environment:
PGPASSWORD: app_pass
Exercises¶
The full walkthrough (distribute a table, verify real shard balance, feel the cross-shard query cost, simulate a hot key) lives in the lab's README:
labs/sharding-citus/README.md on GitHub
git clone https://github.com/sanketn26/interview-prep
cd interview-prep/labs/sharding-citus
docker compose up -d --wait coordinator worker1 worker2 worker3
docker compose up cluster-init
Apple Silicon / arm64
Citus only publishes linux/amd64 images — Docker runs it under emulation on an arm64 host. Works fine, just slower to start.