Learn Labs
Security & Backup

Row Policies, Quotas & TLS

Row-level security, limits, encryption

Users and roles control what a user can query. Row policies control which rows they see when they run that query, and quotas control how much of the cluster's resources they're allowed to consume doing it. Both exist to let one ClickHouse cluster safely serve multiple tenants or teams instead of needing a cluster each.

Row policies: filtering rows per user, transparently

A row policy attaches a filter condition to a table. Any query against that table from a matching user has the condition silently ANDed into its WHERE clause — the user never sees rows outside the filter, and doesn't need to remember to add the filter themselves.

CREATE ROW POLICY tenant_isolation ON analytics.events
  FOR SELECT USING tenant_id = currentUser()
  TO tenant_role;

Here, a user's own name doubles as their tenant identifier via currentUser() — a common pattern when each tenant maps to a dedicated ClickHouse user. More typically the condition references a session setting or a mapping table rather than the username directly, but the mechanism is the same: the policy is enforced by ClickHouse itself, not by application code remembering to filter correctly on every query.

Quotas: limiting how much a user can consume

A quota caps resource usage — queries, errors, rows read, execution time — over a rolling interval, per user or role. It doesn't make individual queries faster; it protects everyone else on a shared cluster from one runaway report, one misbehaving job, or one accidental SELECT * over a trillion-row table.

CREATE QUOTA dashboard_limits
  FOR INTERVAL 1 HOUR
  MAX QUERIES 1000,
  MAX EXECUTION TIME 3600
  TO analytics_reader;

When a user tied to this quota exceeds it, further queries are rejected until the interval resets — a blunt but effective circuit breaker that requires no application-side rate limiting.

Network security, briefly

Two settings matter most day to day: listen_host controls which network interfaces the server accepts connections on (default configs often bind to all interfaces, which is fine inside a private Docker network but not on an open host), and tcp_port_secure / HTTPS enable TLS for the native and HTTP protocols respectively. In a replicated or sharded cluster, an interserver_http_credentials secret authenticates traffic between replicas and shards themselves, separate from any client-facing user — worth knowing exists, mostly a config-file concern rather than a deep concept.

On this page