chlift preview Install with deemwar's help
Postgres → ClickHouse, self-managed · preview

Your Postgres data in ClickHouse, kept in sync, with proof both sides agree.

chlift takes a snapshot of your Postgres tables into ClickHouse, keeps them current with live change data capture, and checks that both sides hold the same data. It is for teams that run their own Postgres and need analytics without hurting it.

chlift is free and MIT licensed. The only paid offers are installation, support and training: io@deemwar.com

What we measured

One recorded run on 2026-10-03, from empty nodes and an empty ClickHouse. Every command is on a terminal recording with real timing, and nothing was typed or edited by hand. Setup: one shared 8-core Linux server (other workloads running too); two ClickHouse 26.3 replicas plus Keeper in containers capped at 1.5 GB RAM each; PeerDB on the same server; Postgres 16 with default settings in 768 MB; synthetic data from chlift seed (about 14M rows, 2.6 GB). This is not a vendor benchmark.

2m22s

Install from empty nodes

chlift install set up 3 hosts plus PeerDB, and all checks passed. The hosts are containers on one server; packages come from the official ClickHouse repo.

≤ 2m26s

14,000,000 rows into both replicas

8M + 4M + 2M rows copied by migrate start to both ClickHouse replicas. An upper bound: status was polled every 15 s.

0 of 64 buckets differ

Equal after live changes

After 50,000 inserts, 1,000 updates and 5,000 deletes over live CDC, migrate check --checksums found every day equal in Postgres and on both replicas (8,047,000 / 4,000,000 / 1,998,000 live rows). The checksums compare counts, ids, integers, timestamps and text lengths per primary-key range. JSON and float columns are not compared.

1m52s

Cutover, end to end

migrate cutover waits for PeerDB to confirm the watermark, then requires equal day counts and 0 of 64 differing checksum buckets on every replica for all 3 tables before it stops the mirror. ClickHouse keeps the data, and check still matches afterwards. Recorded with a later build that also compares rows below Postgres's lowest id.

Query time

14× to 163× faster than Postgres while PeerDB is still replicating (ClickHouse queries use FINAL). 31× to 308× faster without FINAL, which is what you get after cutover or for append-only tables.

Query (median of 5 runs, ms)PostgresClickHouse FINALClickHouse
Daily active users, last 30 days5,388266107
Events per kind per week, 6 months21,9501,600710
Top 10 accounts by events, last 7 days5,74015957
p95 latency per endpoint, last 30 days23,99414778
  • Median of 5 runs per query, all taken in one invocation. The raw samples and a script that recomputes this table are published with the recording.
  • Postgres time is measured from the client and includes sending the result; ClickHouse time is the server's own elapsed time.
  • Postgres runs with default settings in 768 MB. A tuned Postgres on bigger hardware would narrow the gap. Your data and queries are the real test.

Two silent data bugs, reproduced on camera, and what chlift does about them

Replication that fails loudly is annoying. Replication that quietly gives you wrong numbers is worse. In the recording we removed chlift's own requirement on purpose to show what happens without it. Nothing reported an error until migrate check failed.

Deleted rows that stay alive

Without REPLICA IDENTITY FULL, after 4,000 updates and 1,000 deletes Postgres had 19,000 rows and both ClickHouse replicas 20,000.

Long text that arrives empty

In the same run, long texts reached ClickHouse empty. In one checksum bucket: 120,124 bytes of text in Postgres, 1,335 in ClickHouse.

What chlift does

migrate plan requires REPLICA IDENTITY FULL on every table it moves and gives you the ALTER TABLE to run before anything is copied. With the requirement in place, the same kind of changes gave 18,000 = 18,000 = 18,000 rows and 0 of 64 differing buckets.

Install

chlift v0.1.0-preview is one binary for Linux (amd64 or arm64). The script downloads it, checks it against the release's SHA256SUMS and against the checksums written into the script, and installs it only if both match.

curl -fsSL https://chlift.deemwar.com/install.sh | sh

Prefer to read it first: install.sh. Or download by hand: linux-amd64 · linux-arm64 · SHA256SUMS, then run sha256sum -c SHA256SUMS --ignore-missing.

Then

chlift init --cluster prod \
  --host a=10.0.0.1:clickhouse,keeper --host b=10.0.0.2:clickhouse,keeper --host c=10.0.0.3:keeper,peerdb
chlift plan                       # probes every host; changes nothing
chlift install                    # ClickHouse replicas, Keeper, PeerDB over SSH
chlift verify

export CHLIFT_PG_DSN='postgres://USER:YOUR_PASSWORD_HERE@db:5432/app'
chlift migrate plan               # writes chlift-migration.yaml for you to review
chlift migrate start --apply-postgres
chlift migrate check --checksums  # every day and every key range, on every replica
chlift migrate cutover
  • Hosts: Debian/Ubuntu (tested) or RHEL-family (written, not yet tested), SSH key access, Docker with compose v2 on the PeerDB host.
  • Postgres 12+ with wal_level=logical. Managed Postgres (RDS/Aurora) is not tested yet.
  • Preview: replicated targets stay preview until the fault soak passes.

What works today, and what doesn't yet

Recorded end to end

Install from empty nodes; migrate plan, start, status, check with checksums; live CDC; cutover; the bench. The recording also turned up four bugs, all fixed in this release.

Still preview

A replication reliability run under injected faults is still in progress. Until it passes, replicated targets stay marked preview. We have not reproduced the known PeerDB row-loss issue with a Distributed target; chlift avoids that layout.

Install today

Release binaries for Linux amd64 and arm64, checked against SHA256SUMS: install. Or deemwar installs it with you: tell us about your setup below.

Talk to us

Tell us about your Postgres and what you want in ClickHouse. A person replies, usually within a working day. Or email io@deemwar.com.

Running a quick security check…