Apache Kafka to ClickHouse ingestion

Loading Kafka topics into ClickHouse with the Kafka table engine and materialized views, planned around consumer groups, formats, at-least-once delivery and durability for analytics pipelines.

On this page

How Kafka to ClickHouse ingestion works and what it takes to run

The supported way to get Kafka topics into ClickHouse is the Kafka table engine combined with a materialized view that writes into a MergeTree target table. The Kafka table engine acts as a consumer: it reads messages from topics, and the materialized view moves the rows into the table your analysts query. Both products are open source under the Apache License 2.0 (SPDX: Apache-2.0), so the pipeline carries no license fee from either project, while ClickHouse Inc. sells a managed service separately. Your team owns the decisions that shape the data: topic partitioning and keys, the consumer group name and its behavior, the column layout and sorting key of the target table, retention, and backups. ClickHouse executes the consumption and insert logic, but it does not decide whether a message is a duplicate, whether a schema change is safe, or whether a backup can be restored.

Plan the consumer side first. Each Kafka table engine instance joins a consumer group, and Kafka assigns partitions across the consumers in that group, so parallelism depends on your topic partition count and on how many consumers you run. Consumer and insert behavior, the data format, and the settings that control batching and offset handling are configured on the table, and they should be validated against representative traffic in a pre-production environment before go-live. Confirm the exact setting names and defaults for your ClickHouse version in its Kafka engine documentation, because they change between releases. Also confirm how your version commits offsets relative to inserts, since that determines whether a crash can cause redelivery. Plan for at-least-once behavior: duplicates are possible after failures, so the target table or the queries must tolerate them, for example through a deduplicating table design or a unique event identifier. Choose the ClickHouse release line deliberately, since the ClickHouse production FAQ recommends stable releases for most production use and reading the changelog before each upgrade.

The durability of the target data is separate from the Kafka side. ClickHouse replication with ReplicatedMergeTree tables depends on ClickHouse Keeper, and the replication guide recommends at least three Keeper nodes on dedicated hosts in production. Replication protects against host loss but not against bad deletes or corruption, so schedule backups with BACKUP and test restores on a spare cluster, because an untested backup often fails when you need it. Kafka retention is also a constraint: if a consumer stops for longer than the topic keeps messages, the gap cannot be refilled from Kafka. Confirm retention windows, the replay procedure for a bad batch, and who approves offset resets before the pipeline carries production data.

What you need before creating the first Kafka table

Before any Kafka engine table exists, the versions, cluster, replicas and test environment have to be in place. Each card below is a prerequisite that is easy to skip and expensive to retrofit once data is flowing into ClickHouse.

Confirm supported ClickHouse line

Check the ClickHouse security policy to see which release lines currently receive security updates, and pick a line from that list rather than an older build. Most production teams should follow stable releases, and LTS lines suit teams that want fewer upgrades. Read the changelog before each upgrade, because minor backward-incompatible changes can occur. Confirm the exact build you will run before writing any DDL.

Confirm supported Kafka release

Check the Kafka downloads page for the supported 4.x releases and plan to run one of them. Kafka 4.x runs only in KRaft mode, so the cluster you connect to should not depend on ZooKeeper. Record the exact broker version, because the client library and protocol behavior you test against must match what production will run.

A running Kafka cluster with topic and credentials

Have the source topic created with a planned partition count, retention and access rules before you configure ClickHouse. Create a dedicated principal for ClickHouse with read access only to the topics it needs, and a consumer group name reserved for it. Confirm which SASL mechanism and TLS listener the cluster exposes, since the Kafka table settings must match them.

ClickHouse Keeper on dedicated nodes

Replicated tables depend on ClickHouse Keeper, which replaces ZooKeeper. The replication guide recommends at least three Keeper nodes on dedicated hosts in production, with about 4 GB of RAM on each. Keeper nodes should not share hosts with ClickHouse data nodes, so that a data-node failure or heavy merge does not also cost you the coordination quorum.

Network reachability to brokers

ClickHouse servers must reach every broker address that clients receive in cluster metadata, not only the bootstrap address. Check DNS names, advertised listeners and firewall rules from each ClickHouse node, including the ports used for TLS. A test from a single host can pass while a different replica fails, so run the connectivity check from every ClickHouse node.

Pre-production environment with real data shape

Build a pre-production ClickHouse cluster that receives representative messages, including malformed records, schema variants and peak throughput. Run the same queries your analysts will use, and test restores from backup on that environment. Ask your team to define what the pilot must prove before go-live, such as lag under a target and correct row counts after a broker restart.

Configuration sequence from topic to queryable table

This sequence moves a Kafka topic into a ClickHouse table in a fixed order, so each object can be checked before the next one depends on it. The result is a target table that receives new rows continuously, with offsets and row counts you can verify.

  1. Confirm the topic and message format

    Before any ClickHouse object is created, the team that owns the topic confirms the topic name, partition count, retention, the serialization format (for example JSON or Avro) and the field names and types in each message. Nullable fields, timestamps and nested structures are noted now because they determine column types later. Done means the team has a written field list and a sample of recent messages read with a Kafka console consumer from the same brokers ClickHouse will use. Confirm the producer's schema change process, since a silent field change will break the materialized view.

  2. Create the target MergeTree table

    Create the destination table that holds the data permanently, using MergeTree for a single node or ReplicatedMergeTree when the cluster has replicas coordinated by ClickHouse Keeper. Choose the ORDER BY key and partitioning from the query patterns you expect, not from the Kafka partition layout. Done means the table exists on every replica, the schema matches the field list from the previous step, and an INSERT of a test row followed by a SELECT returns that row. Check replication status with the system tables if you use ReplicatedMergeTree.

  3. Create the Kafka engine table

    Create a table using the Kafka table engine with the broker list, topic name, consumer group name, and message format as engine settings, with columns matching the target table. Set the consumer group to a name that no other pipeline uses, because offsets are tracked per group. The Kafka engine table does not store data; it only consumes. Done means the table exists and the broker connection settings are correct. Check that errors appear in the system logs or the error columns if the format does not parse, rather than assuming the table is working.

  4. Create the materialized view

    Create a materialized view that selects from the Kafka engine table and inserts into the target table, mapping each column explicitly. Each batch consumed from Kafka triggers the view, so this object is the step that moves rows. Done means the view exists and points to the correct source and target. Produce a small set of test messages to the topic and confirm that rows appear in the target table within the view's processing cycle, with no duplicate rows from the test.

  5. Verify that consumer offsets advance

    Check the consumer group with the Kafka admin tooling used for your cluster, such as the consumer group describe command, to confirm that the group has committed offsets on every partition and that lag is moving toward zero during a quiet period. Offsets that never advance usually point to a broker connection, authentication or format problem. Done means each partition shows a committed offset and lag returns to a steady low value after new messages stop. Record the group name and the baseline lag in the runbook.

  6. Compare row counts with the source

    Compare row counts in the target table against the message count produced to the topic over the same window, using timestamps or offsets as the boundary. Differences show up as missing rows from parse errors, a view that was created after data was produced, or retries after a failure. Done means the counts agree for the chosen window, or the team has documented the cause of each difference. Confirm the window and boundaries in writing before the comparison, so the result can be repeated during review.

  7. Document the pipeline and its objects

    Record every object created in the sequence, including the topic, consumer group, engine settings, view definition, target table and the access accounts used, in version control alongside the DDL. Note who owns the topic schema and who must be told before a change. Done means a new engineer can rebuild the pipeline from the stored DDL and the runbook, and the verification queries from the previous steps are saved with it. This record is also the starting point for later changes, such as adding columns or a second consumer group.

Consumer groups, parallelism and formats by workload

A single-table pipeline has one Kafka topic feeding one ClickHouse table through a Kafka table engine and a materialized view that writes into a MergeTree target. The main decision is how many consumers read the topic. Kafka assigns each partition to at most one consumer in a consumer group, so a single table instance on one replica reads every partition of the topic, and that is often enough for moderate event volumes. Keep the group identifier stable, because changing it causes the table to start from a different offset position. In this shape, the team mostly needs to confirm that the materialized view writes to the target table without dropping rows during schema or format errors.

  • Consumer count: One Kafka table instance reads all partitions unless you deliberately create more consumers.
  • Group identifier: Set the consumer group name explicitly so restarts and upgrades resume from committed offsets.
  • Target table: Use a MergeTree family table as the destination so the materialized view writes rows into durable storage.
  • Error handling: Decide how malformed messages are handled before go-live, since a single bad record can stop a simple pipeline.
  • Monitoring: Track consumer lag on the group so you can see whether one consumer keeps up with production.

Before building, confirm in the ClickHouse Kafka engine documentation for your version which settings control consumer count, error tolerance and offset behavior.

How at-least-once delivery and durability settings shape the data

Kafka consumers that load into ClickHouse through the Kafka table engine and a materialized view should be designed on the assumption that some rows will arrive twice. The usual failure is simple: the consumer inserts a batch into ClickHouse, the process restarts or the insert response is lost before the consumer commits its offsets, and the same messages are read again from the last committed position. This is at-least-once delivery. A failed insert on the ClickHouse side can produce the same effect, because the client cannot always tell whether a write landed. The target design has to absorb duplicates, either through a deduplicating table engine, a stable business key that makes repeated rows identifiable, or a query-side rule that collapses them. Decide which of these applies before the first production load, because changing the table key later means rebuilding the data.

ClickHouse durability comes from replication rather than from the Kafka side. Tables built on ReplicatedMergeTree are coordinated through ClickHouse Keeper, which replaces ZooKeeper, and the replication guide recommends at least three Keeper nodes on dedicated hosts in production, with about 4 GB of RAM each. When a replica fails and later recovers, it automatically syncs missing data from a healthy replica without manual steps, which is why a single replica loss is usually an operations event rather than a data event. Confirm the Keeper topology, the replica count per shard and the behavior of your insert quorum settings in a test cluster, since those settings decide how many replicas must acknowledge a write before the insert is reported as successful.

Replication is not a backup. The ClickHouse replication documentation is explicit that replicas copy mistakes too: a bad DROP, a faulty ALTER or a corrupting load reaches every replica. Plan BACKUP and RESTORE jobs to local disk, S3-compatible storage or Azure Blob Storage, and keep incremental backups on a schedule that matches how much data you can afford to reload from Kafka. Kafka retention is part of this plan, since topics only replay what they still hold. The ClickHouse backup documentation warns that a backup never test-restored will probably not restore when needed, so schedule restores onto a spare cluster and record how long they take.

Mapping Kafka message fields to ClickHouse columns

This table maps each Kafka concept to the ClickHouse object that receives it, from the topic-to-engine-table link to timestamps and schema drift. Read it as a checklist for the table definition, then confirm each choice against your own producer payloads before the first load.

Kafka conceptClickHouse objectDesign choiceWhat to confirm
TopicKafka engine tableOne engine table per topic, with the broker list and topic name set in the table definitionTopic names and broker addresses match the cluster the ingestion user can reach
Message valueTyped value columnsMap each field of the serialized payload to a column with an explicit type, rather than storing the raw message in one string columnField names and types against sample messages from every producer version
Message keyKey column (String or typed)Store the key when it identifies entities for deduplication or joins, and decode it with the same type the producer usesWhether producers set keys at all, and whether keys are stable across retries
Partition and offsetMetadata columns exposed by the Kafka engineExpose partition and offset as virtual columns in the materialized view, which gives each row a position for tracing and dedup checksThe column names available in your ClickHouse version
Consumer groupConsumer group setting on the engine tableGive each engine table its own group so that offsets for one target table do not interfere with anotherGroup naming convention and whether two tables read the same topic
Event timestampDateTime or DateTime64 columnUse the producer's event time for analytics and keep the broker log time as a separate column when both matterTimezone handling and the precision the producer writes
Nullable or missing fieldsNullable columns or defaultsUse Nullable only where absence is meaningful, and set defaults elsewhere so that a missing field does not stop the viewHow each producer omits optional fields and what the analyst expects for zero versus null
Schema change in producersEngine table and materialized view definitionsAdditive fields need a new column and a view change, and removed or retyped fields need a planned cutover, because the engine table does not follow producer changes on its ownWho approves schema changes and how old and new message versions overlap during rollout

Securing the Kafka-to-ClickHouse path

The ingestion path has three access points: the Kafka brokers that the ClickHouse Kafka engine reads from, the topics and consumer groups it is allowed to use, and the ClickHouse users who query the result. Each needs its own authentication, authorization and encryption decisions, and they should be reviewed together before the first topic goes live.

Choose a Kafka authentication mechanism

Kafka authenticates clients over SSL or SASL. The documented SASL options include GSSAPI (Kerberos), PLAIN, SCRAM-SHA-256, SCRAM-SHA-512 and OAUTHBEARER. For a ClickHouse consumer, SCRAM-SHA-512 or OAUTHBEARER are common choices when your identity platform already issues credentials, and PLAIN should only run over TLS. Confirm which SASL mechanisms and credential settings the Kafka engine in your ClickHouse version accepts before you fix the broker listener design.

Encrypt client and broker traffic

Kafka supports SSL/TLS between clients, brokers and tools. Security is optional in Kafka, so a cluster can run an unsecured listener next to a secured one. For this pipeline, the ClickHouse-to-broker connection should use a TLS listener only, with certificates issued by an authority your team controls and a documented renewal process. Check that the broker listener used by ClickHouse is not an unsecured port left over from testing.

Grant the consumer group read access only

In KRaft clusters, the StandardAuthorizer stores ACLs in the metadata log. Resources without an ACL are limited to super users unless allow.everyone.if.no.acl.found is set to true, so leave that setting off. Create ACLs that grant READ on the specific source topics and on the consumer group the ClickHouse table uses, and nothing broader. Test that the ClickHouse principal is denied on an unrelated topic.

Separate ClickHouse users, roles and grants

ClickHouse access control uses users, roles and grants. Create a dedicated user for ingestion that can read the Kafka engine table and write to the target table, and separate users for analysts who only query. Limit who can create or alter Kafka engine tables, because those objects hold broker credentials. Review grants after each schema change and keep administrative accounts out of day-to-day pipeline roles.

Plan external authenticators for analysts

ClickHouse can delegate user authentication to LDAP directories, Kerberos, SSL X.509 certificates, an HTTP authenticator and JWT. If your organization already runs one of these, using it for analyst access avoids a second password store and lets offboarding happen in one place. Confirm which method your ClickHouse version and client tools support, and test that a removed directory account loses query access.

Confirm the engine credential settings first

Before you write the Kafka engine definition, confirm the exact credential and SSL setting names for your ClickHouse version in its documentation. Passwords and key paths placed in table definitions can appear in logs, system tables and backups, so decide how they will be stored and who can read them. Record the version you tested so that a later upgrade triggers a repeat of this check.

Common ingestion failures and how to fix them

This table lists the failures most often seen when loading Kafka topics into ClickHouse through the Kafka table engine and materialized views. Each row gives the likely cause, how to confirm it on your own cluster, and the fix, so you can work from symptom to resolution. Read it during pilot testing and keep it with the runbook for the pipeline.

FailureLikely cause and how to confirmFix
Consumer lag keeps growingThe topic has more partitions than the consumers in the group can read, so some partitions sit idle while others fall behind. Confirm with the consumer group lag per partition from your Kafka admin tools and compare partition count with the number of ClickHouse consumer threads.Align the table's consumer count and the topic's partition count, raise parallelism where the hardware allows, and check whether inserts into the target table are the bottleneck before adding consumers.
Parse errors on ingestThe message format in the topic does not match the format declared on the Kafka table, such as JSON with a changed field type or an unexpected delimiter. Confirm by inspecting the rejected messages and the error entries in the ClickHouse server log.Agree the format and schema with the producer team, change the table definition in a controlled release, and decide whether bad messages should be skipped or routed to a separate topic for review.
Duplicate rows after restartsOffsets were committed after the insert was lost, or a restart replayed messages that had already reached the target table. This is the at-least-once behavior of the pipeline. Confirm by comparing row counts for a known key range against the source.Design the target table so duplicates collapse, for example with a ReplacingMergeTree engine and a deduplication key, and test a replay in a pre-production environment before relying on it for reports.
Materialized view fails silently on insertThe view's SELECT references a column or type that no longer matches the source table, so the view stops writing while the Kafka table keeps consuming. Confirm by checking the target row count over time and the ClickHouse server log for errors on the view.Monitor the target table's freshness independently of the Kafka table, add alerts on error logs, and recreate the view after any schema change, testing the change against representative data first.
Replicated table stops accepting writes after Keeper failureClickHouse Keeper has lost quorum because fewer than a majority of its nodes are healthy, which blocks coordination for ReplicatedMergeTree tables. Confirm with the Keeper node status and replica health views on the affected replicas. The replication guide recommends at least three Keeper nodes on dedicated hosts in production.Restore a Keeper majority first, keep Keeper on dedicated hosts with enough memory, and verify that recovered replicas resync missing data from a healthy replica before resuming ingestion.
Consumer group access deniedThe Kafka ACLs do not grant the consumer group read permission on the topic or the group itself, or the ClickHouse user is not authenticated with the expected principal. Confirm with the broker authorization logs and the ACL listing for the topic and group.Grant the principal read access on the topic and group in the Kafka authorization configuration, verify the SASL or TLS identity the table uses, and avoid broad allow rules that would hide later misconfiguration.

Backing up the analytics tables and proving restores work

Backups for this pipeline have to cover two things at once: the ClickHouse tables that hold the loaded data and the Kafka consumer offsets that record how far each table has read. ClickHouse BACKUP and RESTORE can take full and incremental backups of tables, partitions or whole databases to local disk, S3-compatible storage or Azure Blob Storage, according to the ClickHouse backup documentation. That documentation also notes that replication does not protect against human error or corruption, so a bad DROP or a corrupted part is copied to every replica. Decide the backup destination, retention and schedule before go-live, and confirm with your storage team that the destination meets your recovery requirements.

Offsets and target tables must be restored as a pair. If the tables roll back to a backup taken at one point while the consumer group resumes from a later committed offset, rows between the two points are lost, and if the reverse happens, rows are loaded twice. Plan the restore runbook so that the backup timestamp, the consumer group offsets for the source topics and any materialized view targets are recorded together, and so that the consumer group is stopped while the tables are restored. Confirm how your Kafka consumer group offsets are captured and reset in your own environment before relying on that sequence, since the exact procedure depends on your Kafka version and tooling.

The point most teams miss is that an untested backup is an assumption. The ClickHouse backup documentation warns that a backup never test-restored will probably not restore properly when needed, and it recommends regular restore tests on spare clusters. Schedule a restore into a separate ClickHouse environment on a recurring basis, check row counts and key aggregates against the source, and replay a known window of Kafka data to confirm that the restored offsets produce no gaps or duplicates. Record the time each restore takes, because that figure is what your recovery objective depends on, and ask your implementation partner to include the restore test in the written scope.

Questions teams ask before building Kafka to ClickHouse ingestion

What does a Kafka to ClickHouse ingestion project cost?

The cost depends on how many topics, partitions, formats and target tables the pipeline covers, plus how much replication and backup work the ClickHouse side needs. Kafka and ClickHouse are both open source under the Apache License 2.0, so there is no license fee for the software itself. The costs that remain are infrastructure you run (brokers, ClickHouse hosts, dedicated Keeper nodes, backup storage), staff time to design and build the pipeline, and ongoing operations. Ask for a quote that separates one-time build work from recurring support, and that lists the topics, formats and tables in scope so the price can be compared line by line.

What makes the effort grow or shrink?

Effort rises with the number of topics and target tables, the number of message formats (JSON, Avro or Protobuf with a schema registry, for example), how often producers change schemas, and the number of partitions that must be read in parallel. Replication and backup scope add work too: a single ClickHouse node with a tested backup is a smaller job than a replicated cluster with Keeper coordination and restore drills. Error handling for malformed messages and the dead-letter path also grows with the number of sources. Each of these should appear as a named line item in the written scope.

How long does a first pipeline take to reach production?

The duration depends on the number of topics, how clean the message formats are, whether the ClickHouse cluster already exists, and how much pre-production testing the business requires. No fixed figure applies across environments, so treat any single number with caution. A practical plan separates the work into schema and query design, a test pipeline fed with representative data, a load and restart test, and a production cutover. Ask the delivery team to show the milestones and the exit criteria for each one before work starts.

What must our team provide before the work starts?

Start with access and data: a Kafka cluster endpoint with a service identity for the consumer group, the topic list, and sample messages from each producer so the table definitions match real payloads. Next, provide the target query patterns, because they decide the table ordering keys and the materialized view design. On the ClickHouse side, you need the hosts or the cluster name, the planned number of ClickHouse Keeper nodes (the replication guide recommends at least three, on dedicated hosts in production), network paths between the two systems, and an environment where tests can run without touching production data.

Can our in-house team build this without a partner?

Yes, if the team already runs Kafka and ClickHouse and has someone who can own consumer group behavior, table design and restore testing. A partner is most useful when the team lacks one of those skills or needs the pipeline delivered on a fixed schedule. The skills to check are Kafka consumer offsets and rebalancing, ClickHouse table engines and materialized views, durability settings, and backup and restore. Decide early who will operate the pipeline after launch, since that person needs the runbooks and alerts as much as the build.

Does ClickHouse Cloud change the ingestion work?

ClickHouse Cloud is a managed service sold by ClickHouse Inc., and it changes who runs the database, not the core design of the pipeline. The Kafka table engine, materialized views, consumer group settings and formats still need the same decisions. What shifts is hosting, replication, Keeper management and backup operation, which the managed service handles under its own terms. Confirm with the vendor which of those tasks it takes on, how backups are configured and restored, and which network paths the Kafka brokers need, because those answers decide how much of the operations section still applies to your team.

How do we verify at-least-once delivery and avoid duplicate rows?

Kafka consumers commit offsets after processing, so a restart can replay messages and produce duplicates in ClickHouse. Plan for at-least-once delivery and design for it: use a table engine and deduplication approach that tolerates replays, include a stable event identifier in every row, and test what happens when a ClickHouse node or the consumer restarts mid-batch. Count rows against a known source sample during the test phase. Make the check part of the acceptance criteria, not an afterthought after launch.

How do we protect the pipeline and its backups?

Replication protects against a failed node, but it does not protect against human error or corruption, so the ClickHouse backup documentation expects a separate backup plan. Use BACKUP and RESTORE to local disk, S3-compatible storage or Azure Blob Storage, and schedule restore tests on a spare cluster, because a backup that was never test-restored will probably not restore when needed. On the access side, Kafka supports SASL and TLS, and ClickHouse supports LDAP, Kerberos, X.509 certificates and JWT as external authenticators. Confirm which of these your identity setup already uses before design starts.

How DeployOpen scopes and delivers this integration

DeployOpen approaches Apache Kafka to ClickHouse ingestion as a written, fixed-scope engagement inside your own infrastructure. We agree the topics, consumer design, table layout and durability settings with your team before the build starts, then test and document the pipeline so your engineers can operate it.

How we scope

  • Inventory the Kafka topics, message formats and expected event volumes that will feed ClickHouse tables
  • Agree consumer group design, partition parallelism and the ClickHouse cluster layout in writing
  • Confirm the Kafka and ClickHouse versions you run, and which ones the project and vendor currently support

How we build

  • Configure Kafka table engine consumers, materialized views and target MergeTree tables in a pre-production environment
  • Test at-least-once behavior, duplicate handling and recovery after broker and ClickHouse node failures
  • Set authentication, TLS and ClickHouse access control to match your existing identity and network policy

How we hand over

  • Document topic-to-table mappings, consumer settings, offset and retry behavior and the durability configuration
  • Provide runbooks for consumer lag, schema changes, backup restore tests and ClickHouse upgrade checks
  • Walk your platform and data engineers through operating the pipeline before handover is accepted

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer after handover
  • Retainer scope, response expectations and review cadence are agreed in writing, so confirm them in your quote
  • Upgrades to new Kafka or ClickHouse releases are planned and tested in a non-production environment first

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.