What Infralytiqs needs from your server

Less than you might expect. A reachable HTTP endpoint, and credentials that can create a database and a table. That is the whole requirement — everything else on this page is about running it well rather than getting it working.

On first save, Infralytiqs runs CREATE DATABASE IF NOT EXISTS followed by CREATE TABLE IF NOT EXISTS <db>.website_events. If you ticked the cluster option and named a cluster, the table is created ON CLUSTER with a ReplicatedMergeTree engine instead of a plain MergeTree. Nothing else is ever created, and nothing outside that database is touched.

Pick a deployment

All three are supported identically. The difference is who carries the operational burden.

A container, for evaluation

One command, about a minute, costs nothing. Ideal for wiring up an integration and deciding whether you like the product. Not suitable for production — no replication, no backups, and its durability is whatever your Docker volume gives you.

ClickHouse Cloud

Managed, with a free tier to start. Backups, upgrades and replication are handled for you, and you get an HTTPS endpoint with credentials to paste into the connection form. The right default unless you already run databases.

Self-hosted

Your own nodes, your own rules. Cheapest at volume and the only option when data residency is contractual, but you own replication, backups, upgrades and monitoring. Use a replicated cluster; a single node will eventually lose data.

Standing one up

The container is for evaluation. The Compose file and the SQL after it are what you would actually run.

# Evaluation only. Not exposed, not replicated, not backed up.
docker run -d \
  --name infralytiqs-clickhouse \
  -p 8123:8123 -p 9000:9000 \
  -e CLICKHOUSE_USER=infralytiqs \
  -e CLICKHOUSE_PASSWORD='change-me-locally' \
  -e CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1 \
  --ulimit nofile=262144:262144 \
  -v infralytiqs-ch-data:/var/lib/clickhouse \
  clickhouse/clickhouse-server:latest

curl -sS http://localhost:8123/ping     # -> Ok.

# The collector runs elsewhere, so its localhost is not yours. Expose this
# through a tunnel for evaluation rather than opening 8123 to the internet:
#   cloudflared tunnel --url http://localhost:8123
#   ngrok http 8123
# Then use the tunnel URL in the connection form.

Sizing

Reference points rather than promises — measure your own compressed row size and scale from there.

Events per month Suggested shape Rough monthly storage Notes
Under 10 million A single node, 2 vCPU, 8 GB RAM Low single-digit GB A container on a small VM genuinely suffices
10–100 million A single node, 4 vCPU, 16 GB RAM, SSD Tens of GB Add backups. Still comfortably one machine
100 million – 1 billion 2 replicas, 8 vCPU, 32 GB RAM each Hundreds of GB Replicate now — restoring from backup at this size is painful
1 billion+ Sharded and replicated, or ClickHouse Cloud TB scale Consider materialised views for your hottest aggregates

Operating it

The queries and commands you will reach for repeatedly.

-- The table arrives with a 24-month TTL. Because ttl_only_drop_parts
-- is set, expiry drops whole parts rather than rewriting data, so it is
-- close to free.

SELECT name, engine, partition_key, sorting_key, ttl_expression
FROM system.tables
WHERE name = 'website_events';

-- Keep less:
ALTER TABLE website_events MODIFY TTL event_date + INTERVAL 6 MONTH DELETE;

-- Keep more:
ALTER TABLE website_events MODIFY TTL event_date + INTERVAL 60 MONTH DELETE;

-- Keep everything:
ALTER TABLE website_events REMOVE TTL;

-- Better than a blunt TTL: move old partitions to cheap storage and keep
-- them queryable, if you have a tiered storage policy configured.
ALTER TABLE website_events MODIFY TTL
    event_date + INTERVAL 3  MONTH TO VOLUME 'cold',
    event_date + INTERVAL 24 MONTH DELETE;

-- Drop one month by hand. Instant, because it unlinks a whole partition
-- instead of deleting rows.
ALTER TABLE website_events DROP PARTITION '202401';

Operational questions

No. It creates and writes one database containing one table, website_events, and reads a few system tables for the storage and health panels. The grant list above is exactly sufficient, which is why giving it your admin account is unnecessary.
You can — it is your table — but prefer custom_dimensions and custom_metrics for anything the collector will populate, since the report builder discovers map keys automatically and an unknown column is not offered anywhere in the UI. Added columns are safe: the platform uses CREATE TABLE IF NOT EXISTS and never drops or recreates the table.
Anything reasonably current. The schema uses Map columns, LowCardinality, ZSTD and Delta codecs, and MATERIALIZED and ALIAS columns — all long-established features. Version 23.8 or later is a safe floor, and staying on a recent LTS is good practice regardless.
No. Put it behind TLS with a reverse proxy, restrict to the paths the platform uses, and if your collector has a stable egress address, add a HOST clause to the user as well. ClickHouse's HTTP interface is powerful, and it is not intended to be an internet-facing surface.
Register the new server as another ClickHouse module — you can copy report suites across when you create it — then re-point your sites. Move historical rows with INSERT INTO new SELECT * FROM remoteSecure(...), one month at a time so you can resume if it is interrupted.
Check system.query_log for what it read. Usually the fix is a skip index on the filtered column, or a materialised view for a panel that is opened constantly. Both are shown above, and both are changes you make yourself without involving us.
ALTER TABLE website_events DELETE WHERE user_id = '...'. It is a mutation and therefore not instant, but it is a genuine deletion rather than a flag. Because the database is yours, you can prove it completed by querying afterwards, which is a materially better position than trusting a vendor's deletion endpoint.

You own the whole stack now

Events flowing in from every surface, into a database you control, queried by a console you did not have to build.