Your MSK-to-ClickHouse® integration looked straightforward in the architecture diagram. Managed Kafka streams feeding real-time analytics. Clean data flow. The proof-of-concept connected successfully from your laptop.
Then you deployed to production in AWS.
Now connections timeout mysteriously. Authentication fails with cryptic SASL errors. Some consumer instances connect while others don't. Security groups look correct but traffic never reaches ClickHouse. Your pipeline oscillates between "working" and "connection refused" with no pattern you can identify.
The problem isn't that MSK and ClickHouse are incompatible. Most teams fundamentally misunderstand that MSK integration complexity lives in AWS networking, authentication model compatibility, and VPC architecture—not in Kafka or ClickHouse configuration.
ClickHouse integration with Amazon MSK follows two architectural paths: native Kafka Engine consumption where ClickHouse pulls from MSK, and MSK Connect Sink where external workers push to ClickHouse. But the real decision that determines success or failure happens earlier: VPC topology, security group configuration, authentication mechanism, and DNS resolution strategy.
Teams familiar with other databases like PostgreSQL will find similar networking and authentication trade-offs when scaling analytics pipelines in AWS.
The choice isn't about features or Kafka expertise—it's about whether your team can debug AWS networking layers and which authentication model your infrastructure actually supports.
The Two Real Integration Paths (And Why Networking Decides Everything)
Before touching Kafka connectors or ClickHouse DDL, understand that network architecture determines which integration patterns are even possible.
Native Kafka Engine: ClickHouse pulls from MSK
ClickHouse includes a Kafka table engine that acts as a native consumer. The typical pattern requires three objects:
- Kafka table (
ENGINE = Kafka) - Stream input from MSK topic - Destination table (
MergeTree) - Persistent storage - Materialized view - Transforms and writes from Kafka table to destination
This is the path with fewer moving parts. No external consumer infrastructure, no separate worker fleet, no additional services to monitor.
Critical requirement: ClickHouse must have network connectivity to MSK brokers. This means route tables, security groups, DNS resolution, and compatible authentication.
When this works: ClickHouse and MSK are in the same VPC, or connected via VPC peering with proper routing. You want transformation logic close to storage (in materialized views). Your team prefers fewer operational components.
When this breaks: ClickHouse is in ClickHouse Cloud (different AWS account), complex VPC topology with multiple accounts, or authentication mechanisms ClickHouse doesn't support natively.
MSK Connect Sink: External workers push to ClickHouse
MSK Connect runs Kafka Connect workers as a managed service. The official ClickHouse sink connector runs in these workers and pushes data to ClickHouse.
Network requirement changes: Now MSK Connect workers need connectivity TO MSK brokers (usually same VPC, straightforward) AND connectivity TO ClickHouse (this is where complexity lives).
If ClickHouse is in a different VPC or account: VPC peering, Transit Gateway, PrivateLink with VPC endpoints, or NAT gateway for internet egress.
These networking layers are often more complex than traditional Apache server deployments, where routing and access rules are handled at a simpler infrastructure level.
When this works: You already operate Kafka Connect for other integrations, want to decouple consumption from ClickHouse cluster resources, or need sophisticated Dead Letter Queue patterns.
When this adds unnecessary complexity: Simple use case with ClickHouse and MSK in same VPC, small team without Kafka Connect experience.
One team: "We spent three weeks getting MSK Connect networking right—VPC endpoints, private DNS, security groups. Then tried native Kafka Engine and it worked in 20 minutes. Same VPC, same auth, zero additional infrastructure."
Why VPC architecture matters more than connector choice
The brutal reality: 80% of MSK-ClickHouse integration failures are network and authentication issues, not Kafka or ClickHouse bugs.
Before choosing a connector: Draw the actual network topology, identify where ClickHouse runs, map required connectivity paths, verify DNS resolution at every hop, and test with basic Kafka CLI tools before building production pipeline.
If you can't connect with kafka-console-consumer.sh from the ClickHouse subnet using the same auth mechanism, your production pipeline won't work either.
MSK Network Architecture That Actually Works
Amazon MSK exposes different ports for different security configurations. Using the wrong port is the number one connection failure cause.
Port confusion: 9092 vs 9094 vs 9096 vs 9098
MSK port matrix (within AWS):
- 9092: Plaintext (unauthenticated)
- 9094: TLS encryption only
- 9096: SASL/SCRAM authentication
- 9098: IAM authentication
The failure mode: Your MSK cluster uses IAM authentication. Your ClickHouse Kafka Engine configuration points to port 9094 (TLS). Connection hangs or times out. Security groups look correct. DNS resolves. Everything "should work."
The problem: Port 9094 is for TLS-only, not IAM. IAM requires port 9098.
Before debugging anything else:
# Test connectivity to MSK broker on correct port
telnet b-1.msk-cluster.kafka.us-east-1.amazonaws.com 9098
If telnet times out, the problem is network (route tables, security groups, NACLs), not authentication.
Security groups and route tables that break silently
Common silent failure:
MSK Security Group:
Inbound: Allow port 9096 from ClickHouse instance security group
ClickHouse instance:
Doesn't have ClickHouse security group attached (wrong SG)
Result: Connection timeout (silently dropped)
Route table issues:
ClickHouse subnet route table:
10.0.0.0/16 -> local
0.0.0.0/0 -> NAT Gateway
MSK in 10.1.0.0/24 (different VPC)
No peering connection route
Result: ClickHouse can't route to MSK
Debugging checklist: Verify security group IDs match, check Network ACLs, confirm route table has path to destination subnet, test with EC2 instance in same subnet, enable VPC Flow Logs to see where packets are dropped.
One customer: "Spent two days debugging 'MSK connection timeout.' Flow Logs showed packets reaching MSK but responses being dropped. Network ACL had explicit deny rule for ephemeral ports. Security groups were perfect."
Authentication Models: IAM vs SASL/SCRAM vs mTLS
MSK supports multiple authentication mechanisms, but not all are equally compatible with ClickHouse Kafka Engine.
IAM authentication: Port 9098 and OAUTHBEARER mechanics
How MSK IAM authentication works: Client uses AWS credentials (IAM role or user), SASL mechanism AWS_MSK_IAM (Java) or OAUTHBEARER (other languages), client library exchanges AWS credentials for Kafka authentication tokens.
ClickHouse Kafka Engine IAM support: IAM authentication compatibility depends on whether your ClickHouse build includes librdkafka with OAUTHBEARER support, correct configuration of SASL mechanism and security protocol, and proper AWS credentials available to ClickHouse process.
Reality check: Many teams struggle with IAM authentication from ClickHouse. The path of least resistance is often SASL/SCRAM.
SASL/SCRAM: The compatibility path for ClickHouse Kafka Engine
SASL/SCRAM is a username/password authentication mechanism that works reliably with ClickHouse.
ClickHouse configuration:
CREATE TABLE kafka_queue
(
event_time DateTime64(3),
user_id String,
event_type String
)
ENGINE = Kafka
SETTINGS
kafka_broker_list = 'b-1.msk-cluster.kafka.us-east-1.amazonaws.com:9096',
kafka_topic_list = 'events',
kafka_group_name = 'clickhouse_consumers',
kafka_format = 'JSONEachRow',
kafka_security_protocol = 'SASL_SSL',
kafka_sasl_mechanism = 'SCRAM-SHA-512',
kafka_sasl_username = 'clickhouse_user',
kafka_sasl_password = 'stored_in_secrets_manager';
Benefits over IAM: Broader client library compatibility, simpler troubleshooting (standard username/password), works reliably with librdkafka in ClickHouse, credentials rotation via Secrets Manager.
One team: "Spent a week trying to get IAM working with ClickHouse Kafka Engine. Intermittent authentication failures we couldn't reproduce. Switched to SCRAM, worked immediately, zero issues in six months of production."
Unless you have specific requirements for IAM (compliance, centralized AWS credential management), SCRAM is the pragmatic choice for ClickHouse integration.
Kafka Engine Pattern: Consumption Mechanics and Tuning
Understanding how the Kafka Engine actually consumes data is critical for performance tuning and troubleshooting.
kafka_num_consumers and partition assignment
Kafka's fundamental rule: One partition can be consumed by at most one consumer in a consumer group.
Setting kafka_num_consumers = 16 with a topic that has 8 partitions: 8 consumers get assigned one partition each, 8 consumers sit idle (waste of resources). No throughput benefit beyond partition count.
Practical formula:
kafka_num_consumers = min(
topic_partitions,
clickhouse_cpu_cores * 0.8
)
One customer had 12-core ClickHouse server, 48-partition topic, and set kafka_num_consumers = 48. Result: Constant CPU saturation, queries slow, consumer lag growing. Reduced to 16 consumers, lag disappeared, query latency improved 3x.
kafka_max_block_size and flush intervals: Throughput vs latency
ClickHouse consumes Kafka in blocks, not message-by-message. Two settings control batching:
kafka_max_block_size: Maximum messages to accumulate before insertingkafka_flush_interval_ms: Maximum time to wait before flushing incomplete block
Throughput-optimized: Large batches (1M messages), long flush intervals (10s) = fewer inserts, better merge management, but 10+ second latency.
Latency-optimized: Small batches (10k messages), short flush intervals (1s) = more frequent inserts, more parts created, but ~1 second latency.
The merge explosion problem: Small, frequent inserts create many small parts on disk. If inserts happen faster than merges can keep up: part count explodes, queries slow down, background merge threads saturate I/O.
Recommended starting point:
kafka_max_block_size = 100000
kafka_flush_interval_ms = 5000
The three-table pattern: Queue, destination, and quarantine
Production-grade pattern requires:
- Kafka queue - Stream input with
kafka_handle_error_mode = 'stream' - Destination table - Persistent storage with Kafka metadata
- Quarantine table - Parse failures captured for debugging
Two materialized views: One routes successful parsing to destination (WHERE _error = ''), another routes failures to quarantine (WHERE _error != '').
This pattern enables: Production pipeline continues despite parse failures, full visibility into what's failing, ability to reprocess quarantined messages, debugging with exact Kafka metadata.
Error Handling Without Breaking Pipelines
Real-world Kafka topics contain malformed messages. Default behavior: parse error throws exception, consumer stops, entire pipeline blocks.
kafka_handle_error_mode='stream' for dead letter capture
Enable stream mode:
kafka_handle_error_mode = 'stream'
Virtual columns available:
_error: Parse error text (only on failure)_raw_message: Original message bytes (only on failure)
Example parse error:
_error: "Cannot parse input: expected opening quote for String value"
_raw_message: {"event_time":"2025-01-20", "user_id":12345}
With this information: Fix producer schema bugs, quantify error rates by topic, reprocess after schema corrections, debug without losing messages.
Use stream mode for production pipelines where data quality matters. Skipping messages blindly creates silent data loss discovered months later.
Schema Evolution: Avro, Schema Registry, and the Glue Problem
JSON is simple but expensive at scale. Avro provides schema versioning, compact encoding, and evolution guarantees.
AWS Glue Schema Registry incompatibility
Here's the trap: AWS provides AWS Glue Schema Registry for schema management in MSK environments. Glue Schema Registry is NOT compatible with Confluent Schema Registry API.
What this means: Producers using Glue Registry serializers create Avro messages, ClickHouse AvroConfluent format expects Confluent wire format, messages fail to parse (wire format incompatibility).
Solutions:
Option 1: Use Confluent Schema Registry (self-hosted or Confluent Cloud)
Option 2: Intermediate transformation - Kafka Streams reads from Glue topic, re-serializes to Confluent format
Option 3: Stick with JSON (if schema evolution isn't critical)
One team: "We had MSK with Glue Schema Registry for six months. Spent a week trying to get ClickHouse AvroConfluent working before discovering the incompatibility. Deployed self-hosted Schema Registry for analytics topics, problem solved."
This compatibility issue is particularly relevant for businesses using streaming data for social media analytics, where schema evolution and real-time ingestion directly impact reporting accuracy and latency.
Observability: system.kafka_consumers and Lag Diagnosis
Operating Kafka Engine in production requires visibility into consumer state.
Monitoring consumer state per partition
ClickHouse exposes system.kafka_consumers table:
SELECT
table,
consumer_id,
assignments.partition,
assignments.current_offset,
assignments.lag
FROM system.kafka_consumers
ARRAY JOIN assignments
WHERE table = 'events_kafka'
ORDER BY assignments.lag DESC;
Key metrics: current_offset (last message read), committed_offset (last offset committed), lag (difference between topic high watermark and committed offset).
Distinguishing Kafka lag from merge saturation
Lag can come from multiple bottlenecks:
Kafka consumption slow: current_offset advancing slowly → Network issues, insufficient consumers
Insert queue backing up: current_offset advancing but committed_offset lagging → Materialized view slow
Merge saturation: Inserts complete but query performance degrading → Too many small parts
Monitor part count:
SELECT table, count() AS parts
FROM system.parts
WHERE active AND table = 'events'
GROUP BY table;
If parts > 1000: You have a merge problem, not a Kafka problem.
How Tinybird Eliminates MSK Integration Complexity
Everything discussed—VPC architecture, authentication mechanisms, security groups, consumer tuning, merge management, error handling—requires deep AWS and ClickHouse expertise.
Tinybird eliminates this operational burden entirely for MSK-to-ClickHouse pipelines.
For teams seeking a managed approach to real-time data ingestion, this architecture removes the need for deep AWS networking expertise.
Native Kafka connectors with automatic MSK authentication
No VPC peering. No NAT gateways. No security group debugging.
Tinybird provides native MSK connectors with automatic authentication (SASL/SCRAM, mTLS), built-in network connectivity (no VPC complexity), managed consumer infrastructure, and automatic offset and checkpoint management.
You provide MSK connection details and credentials. Tinybird handles everything else.
One customer: "We were three weeks into debugging VPC endpoint configuration for MSK Connect. Tried Tinybird, connected to MSK in 10 minutes. Zero VPC config, zero security groups, just worked."
Zero consumer management or offset tracking
Traditional MSK-ClickHouse architecture requires: Kafka Engine configuration and tuning, or MSK Connect worker fleet management, consumer group monitoring, offset management and checkpointing, rebalancing and resharding adaptation.
Tinybird architecture: Define MSK Data Source with connection details, specify topic and schema, data flows automatically with sub-second latency, zero infrastructure to operate.
Latency comparison:
Self-managed: 2-8 seconds median (P99: 10-20s)
Tinybird: 400-700ms median (P99: 1-2s)
Sub-second ingestion from MSK to queryable APIs
With traditional ClickHouse, after solving MSK connectivity and ingestion, you still need API layer, authentication, multi-tenant data isolation, query parameter validation, and caching strategies.
Choosing the best database for real-time analytics depends not only on ingestion speed but also on how seamlessly your system exposes analytical APIs and manages data latency across pipelines.
Tinybird transforms SQL into production APIs instantly:
SELECT
toStartOfMinute(event_time) AS minute,
event_type,
count() AS event_count
FROM events
WHERE event_time >= now() - INTERVAL {{Int32(hours, 24)}} HOUR
AND user_id = {{String(user_id, required=True)}}
GROUP BY minute, event_type
Becomes:
GET /api/v0/pipes/user_events.json?hours=24&user_id=abc123
Built-in: Type-safe query parameters, authentication via API tokens, automatic multi-layer caching, per-tenant data isolation, sub-100ms query latency.
Real production example: SaaS analytics on MSK
One SaaS company processing 80M MSK events per day:
Before Tinybird: 3 engineers managing MSK and ClickHouse integration, VPC peering and security groups, Kafka Engine tuning, part count monitoring, custom API layer (2,500+ lines), median query latency 900ms.
After Tinybird: Zero VPC configuration, zero consumer management, zero merge tuning, APIs auto-generated from SQL, median query latency 55ms.
Engineering time recovered: 18+ hours/week. Infrastructure cost reduction: 45%.
The fundamental insight: Most teams don't want to operate MSK-ClickHouse integration—they want real-time analytics from streaming data. Tinybird provides the latter without requiring you to become an expert in VPC architecture, Kafka Engine tuning, or merge management.
Modern data teams increasingly rely on real-time dashboards built on top of MSK-ClickHouse pipelines to visualize key metrics instantly. By reducing ingestion latency and automating transformation, platforms like Tinybird make it possible to monitor and react to streaming events within seconds.
Choose Based on AWS Network Expertise and Operational Capacity
ClickHouse integration with Amazon MSK works. Hundreds of companies process billions of events daily through these pipelines.
But "works" and "sustainably operable" are different things.
Native Kafka Engine complexity: VPC connectivity and security group configuration, authentication mechanism compatibility (SCRAM vs IAM), consumer and batch tuning, merge management and part count monitoring, error handling and quarantine patterns.
MSK Connect complexity: VPC endpoints and PrivateLink configuration, private DNS hostname resolution, connector deployment and versioning, DLQ configuration and monitoring, parallel insert limitations at scale.
Traditional path: Hire engineers with AWS networking and ClickHouse expertise. Build and maintain consumer infrastructure. Debug VPC connectivity at 3am. Accept operational burden as the cost of real-time analytics.
Tinybird path: Native MSK connectors with automatic management. Zero VPC configuration. Zero consumer tuning. SQL queries become APIs. Real-time analytics without AWS networking expertise.
For teams building MSK-to-ClickHouse pipelines: choose based on your operational capacity and what you want engineers focused on. Debugging security group rules and tuning Kafka Engine settings? Or building analytics features your customers actually use?
The choice is yours. For most teams, spending weeks mastering VPC endpoint configuration isn't the goal—shipping real-time analytics products is.
