MergeTree tables on what looks like a local file system, and Archil keeps
the files durable in object storage. That gives a self-hosted ClickHouse three properties it doesn’t have on local disks:
- One copy of the data, in object storage. Archil makes a write durable across Availability Zones as soon as
fsyncreturns, so you don’t need ClickHouse replicas to keep the data safe. - Replaceable servers. No table data or metadata lives on the server. When a server dies, another one mounts the disk and starts ClickHouse with every table intact.
- Isolated copies for heavy queries. A branch gives you a writable copy of the whole database in about 50 ms (a 15 ms checkpoint plus a 35 ms branch), whatever its size. Run a long modeling query or a backfill on a second server against the branch, and it never competes with ingest on the primary.
s3 disk, but the server then keeps the metadata for those parts on its
local disk, and sharing one copy of the data between replicas relies on zero-copy replication, which ClickHouse doesn’t
recommend for production. With the data directory on Archil, nothing in ClickHouse needs to know about object storage.
You’ll set up a primary server, load 100 million rows, move the database to a second server, and then run a heavy query
on a branch while the primary keeps taking inserts.
Prerequisites
- Two Linux servers running Ubuntu 22.04 or later, x86-64 or arm64, in the same cloud region as your disk. This guide
calls them
ch-primaryandch-analytics. Any instance with 4 vCPUs and 16 GiB of memory is enough for the examples; we used EC2m7i.xlargeinstances inus-east-1. Both need outbound access to Archil. - An Archil disk for the database, created in the Archil console. Branches need Archil-managed storage or a flat-block bring-your-own-bucket disk; see Branches & Checkpoints.
- A disk token for that disk, which both servers use to mount it. In the console, open the disk, select Connections, click Add User, and choose Disk Token.
- An API key in the disk’s region, for creating branches.
Install ClickHouse and the Archil client
Run this on both servers. It installs the Archil client and ClickHouse from ClickHouse’s official package repository, then stops ClickHouse, which still points at its default data directory on the local disk:install.sh
Point ClickHouse at the Archil disk
Still on both servers, add a configuration file that moves everything ClickHouse needs to restart onto the disk. Thepath setting covers table data, table and database definitions, and ClickHouse’s own state. Users and grants created
with SQL are stored separately, so user_directories moves them too. tmp_path, which ClickHouse uses for large sorts
and joins that spill out of memory, stays on the local disk: it’s scratch space, and it’s faster there.
/etc/clickhouse-server/config.d/archil.xml
fsync the parts it writes, so an INSERT can return before its data is durable. On an
Archil disk, writes that haven’t been flushed are held by the client on that server, and they’re lost if the server dies.
The two merge_tree settings make every INSERT wait until its part is durable, so a server failure never loses an
acknowledged insert. They also make sure a checkpoint contains every insert that finished
before it. Each insert now waits for a round trip to Archil, so send data in large batches, as ClickHouse recommends
anyway, or turn on asynchronous inserts.
Finally, stop ClickHouse from ever starting while the disk isn’t mounted. Without a guard, it would create an empty
database in /mnt/archil on the local disk:
Start the primary
Onch-primary, mount the disk, hand a directory on it to the clickhouse user, and start the server:
archil mount takes the disk in exclusive mode, so ch-primary is the only server that can write to it. That’s what
ClickHouse expects: one server owns a data directory.
Create a table and load 100 million rows of synthetic events:
schema.sql
/mnt/archil/clickhouse.
By default, ClickHouse listens only on
localhost, and its default user has no password, so this guide runs
clickhouse-client on the servers themselves. Before you open ClickHouse to the network, set up users and passwords as
described in ClickHouse’s access control guide, then set
listen_host.Move the database to another server
Because the whole database is on the disk, moving it is a remount. Onch-primary, stop ClickHouse and unmount the disk.
archil unmount flushes every outstanding write before it returns:
ch-analytics, mount the disk and start ClickHouse:
ch-analytics didn’t copy anything. It read the table’s files from Archil as ClickHouse opened them, and anything already
in Archil’s server-side cache was served from there. In our runs, unmounting took about 0.15 seconds, mounting on
ch-analytics 0.1 seconds, and starting ClickHouse about 1 second. The category query from the previous section took
0.9 seconds the first time on ch-analytics, against 0.5 seconds on a server that had already read the table.
When a server dies
If a server crashes instead of shutting down, it still holds the disk, and a normalarchil mount on a replacement fails
with another client has an outstanding delegation to the root of the disk. Once you know the old server is down, take
the disk over with --force:
--force revokes the old server’s ownership of the disk, and any writes it hadn’t flushed are lost. With
fsync_after_insert on, those are only inserts that hadn’t returned yet, and background merges that ClickHouse redoes on
its own. At startup, ClickHouse logs Removing temporary directory for each part that was still being written, and
deletes it, as it would after a crash on a local disk. ClickHouse commits a large INSERT one block at a time, so an
insert that was still running can be partly applied.
We tested this by force-stopping ch-analytics in the middle of an INSERT ... SELECT. --force mounted the disk on
ch-primary in 0.1 seconds, ClickHouse started in about 1 second, every row from inserts that had returned was there, and
no parts were detached as broken.
Move the database back to ch-primary the same way before you continue: stop ClickHouse and unmount on ch-analytics,
then mount and start on ch-primary.
Run heavy queries on a branch
A long query on the primary competes with inserts and with every other query for CPU, memory, and I/O. Instead, take a checkpoint of the running database, branch the disk from it, and run the query onch-analytics against the branch. The
primary keeps running the whole time.
On ch-primary, take a checkpoint with a unique name:
MergeTree commits a part by renaming its finished directory into place, so the checkpoint contains only whole parts, and
every insert that returned before it.
Create a branch from the checkpoint. This needs your API key and the disk ID, and it can run anywhere the archil client
is installed:
ch-analytics, mount the branch and start ClickHouse on it. Pass the same CHECKPOINT value you used on ch-primary:
Status file ... already exists - unclean restart when it starts on the branch, because the checkpoint was taken while
the primary was running; that’s expected.
ch-analytics now has its own writable copy of the database as of the checkpoint. Run the heavy query there:
ch-primary, add 10 million rows:
ch-analytics still has 100 million rows. Nothing either server does reaches the other: the branch can
create tables, run backfills, or drop data without touching the primary.
When you’re done with the branch, stop ClickHouse and unmount it:
remote table function.
Running it in production
- One server per disk or branch. Two ClickHouse servers must never share one data directory, and exclusive mounts
enforce that. To scale writes, shard: give each shard its own disk and query across them with a
Distributedtable. - No replication needed for durability. Use plain
MergeTreetables. ClickHouse Keeper andReplicatedMergeTreeare only worth running if you need a standby that’s already started when the primary fails. - Failover time grows with the number of parts. At startup, ClickHouse reads a few small files from every active part. Keep the part count in check with a sensible partition key and batched inserts, and measure a remount on your own data.
- Size the client cache for your working set. The Archil client caches file data in memory, and by default it uses at
most 2 GiB. On a dedicated ClickHouse server, raise it with
--max-cache-mbwhen you mount. See Client caching. - Mount at boot. The guide’s
ExecStartPrecheck keeps ClickHouse from starting until the disk is mounted, and the service retries every 30 seconds. Mount the disk from your provisioning or a boot script, and ClickHouse starts once the mount appears.
Run it in Archil sandboxes
Everything above also works in persistent sandboxes, and that’s the most cost-effective way to run it: reads between a sandbox and its disks are transfer within Archil, which is free. The officialclickhouse/clickhouse-server
image already includes the archil client in a sandbox. Sandboxes don’t run systemd, so ClickHouse runs as a
sandbox service instead, which restarts if it crashes.
This script sets up the primary. It’s the configuration from earlier in this guide, with ClickHouse registered as a service:
primary-setup.sh
/mnt/archil, upload archil.xml, schema.sql, and the script, and run it:
archil checkpoints create /mnt/archil "$CHECKPOINT", exactly as on a server, and
create branches with archil branches create as before. A sandbox’s mounts attach the disk itself, not a branch, so
the analytics sandbox is created without any and mounts the branch itself with archil mount --branch. Pass the disk’s ID,
region, and token, and the checkpoint name, as environment variables:
analytics-setup.sh
aws-us-west-2, the 100-million-row load took about 7 seconds in a 4 vCPU, 16 GiB sandbox. In the analytics
sandbox, archil mount --branch took under half a second, ClickHouse was ready about 2 seconds later, and the heavy query
from the previous section returned the same result in about 2 seconds. Delete the analytics sandbox when you’re done with
the branch: it mounts the branch from its setup script, so it isn’t meant to be stopped and started again.
Cost compared with ClickHouse Cloud
Running this setup in Archil sandboxes costs 17% to 61% less than ClickHouse Cloud’s published example services. This section compares list prices in AWSus-east-1 as of November 2026: Archil’s Developer and Team rates from
Pricing & Billing, and ClickHouse Cloud’s from its pricing page.
One server instead of two. ClickHouse Cloud’s Scale and Enterprise services keep at least two replicas once they’re
larger than 12 GiB. On Archil, the disk already keeps every write durable across Availability Zones, so one ClickHouse
server per shard is enough. Per unit of compute, a sandbox also costs less:
Storage without a second copy. Archil stores the data for $0.025 per GB-month, or $25 per TB. ClickHouse Cloud charges
$25.30 per TB, and bills its default daily backup as a second copy at the same rate; on Archil, checkpoints take its place.
Archil also bills $0.20 per GiB-month for active data, which is data read or written in the last hour, so the total
depends on how much of the table your queries touch each hour.
Here is the monthly cost of ClickHouse Cloud’s published examples, running 24 hours a day, next to one sandbox the size of
one of their replicas, with 10% and 100% of the data active:
The Archil columns are one sandbox (2 vCPU and 8 GiB, 4 vCPU and 16 GiB, or 16 vCPU and 64 GiB) running all month, plus
storage. A branch sandbox for heavy queries, like a ClickHouse Cloud warehouse, only costs compute while it runs.
To see where your workload falls between the two Archil columns, run it for a day and check the disk’s active data on its
Usage tab in the Archil console.
Clean up
On each server that’s running ClickHouse, stop it and unmount the disk:Next steps
Branches & Checkpoints
How checkpoints and branches work, and their CLI commands.
Mount on Linux
Requirements, authorization, and mount options for Linux servers.
Client caching
Size, warm, and refresh the client’s in-memory cache.
Analytics with DuckDB
Query Parquet in S3 in place, without loading it into a database.