Kafka Overview
TheKAFKA route connects your Coreflux broker to an Apache Kafka cluster and moves messages in both directions. A single route can produce (MQTT → Kafka) and consume (Kafka → MQTT) at the same time, so device telemetry can flow into your data pipeline while commands and setpoints flow back to the field.
When to use it
- Feed real-time MQTT telemetry into a Kafka-based analytics or data pipeline.
- Bring Kafka events (commands, setpoints, alarms) back into the broker for field devices.
- Bridge edge MQTT traffic to a managed cloud platform like Confluent Cloud or AWS MSK.
Key capabilities
| Capability | What it means for you |
|---|---|
| Bidirectional | Produce and consume in one route — no separate definitions needed |
| Secure | Supports PLAINTEXT, SSL, SASL_PLAINTEXT, and SASL_SSL |
| Reliable delivery | Per-message offset commit on the consume path (at-least-once) |
| Message keys | Route records to partitions by topic segment or JSON field for ordered, per-device streams |
| Tunable throughput | Configurable batching, compression, and acknowledgement levels |
| Cloud & self-hosted | Confluent Cloud, AWS MSK, Aiven, Redpanda, and self-managed clusters |
Let’s look at how a Kafka route is defined, starting with the three common directions.
Quick Start
- Produce (MQTT → Kafka)
- Consume (Kafka → MQTT)
- Bidirectional
factory/sensors/pump-01 becomes a Kafka record on factory.sensors.raw with key pump-01.How Kafka Compares to MQTT
Kafka and MQTT solve different problems. Coreflux bridges the two so each does what it’s best at: MQTT for fast device traffic, Kafka for durable, replayable streams.| Feature | Kafka | MQTT |
|---|---|---|
| Delivery model | Pull (consumer fetches) | Push (broker delivers) |
| Retention | Configurable (hours to forever) | Typically none |
| Ordering | Per-partition | Per-topic |
| Fan-out / load balancing | Built-in consumer groups | Shared subscriptions |
| Throughput | Millions of messages/sec | Thousands of messages/sec |
| Typical use | Data pipelines, analytics, replay | IoT telemetry, device control |
| Term | Description |
|---|---|
| Bootstrap servers | The initial broker addresses the route contacts to discover the rest of the cluster |
| Topic | A named, partitioned log of records |
| Partition | An ordered sub-stream within a topic — the unit of ordering and parallelism |
| Consumer group | A set of consumers that divide a topic’s partitions between them |
| Offset | A record’s position within a partition, committed once it has been processed |
Supported Kafka Services
The Kafka route works with any Kafka-compatible cluster, cloud-managed or self-hosted.- Cloud-managed
- Self-managed
| Service | Security Protocol | Notes |
|---|---|---|
| Confluent Cloud | SASL_SSL | PLAIN or SCRAM mechanism |
| Amazon MSK | SASL_SSL | IAM or SCRAM auth |
| Aiven for Kafka | SASL_SSL | SCRAM-SHA-512 typical |
| Azure Event Hubs (Kafka API) | SASL_SSL | PLAIN with connection string as password |
| Redpanda Cloud | SASL_SSL | Kafka-compatible |
Connection Configuration
Every Kafka route starts with aKAFKA_CONFIG block describing the cluster, security, and throughput settings. Only BROKER_ADDRESS is required, but production routes should always set a GROUP_ID and use a secure protocol.
Connection & Security
Cluster Connection
Cluster Connection
localhost:9092 or host1:9092,host2:9092. List two or three brokers in production so the route survives an individual broker restart.Earliest (from the beginning) or Latest (new messages only).false for per-message commit (at-least-once delivery). Set true to additionally enable periodic background commits.Security
Security
PLAINTEXT, SSL, SASL_PLAINTEXT, or SASL_SSL.PLAIN, SCRAM-SHA-256, or SCRAM-SHA-512.GET ENV.GET SECRET to keep it out of your LoT definition.SSL or SASL_SSL).Throughput & Tuning
Throughput & Tuning
0 (no acknowledgement), 1 (leader only), or all (all in-sync replicas).none, gzip, snappy, lz4, or zstd. Most effective on larger batches — pair with LINGER_MS.Security & Authentication
Choose the security protocol that matches your broker’s listener. For anything beyond a local development cluster, useSASL_SSL.
SECURITY_PROTOCOL | TLS | SASL | Typical use |
|---|---|---|---|
PLAINTEXT | No | No | Local development |
SSL | Yes | No | TLS-only clusters |
SASL_PLAINTEXT | No | Yes | Internal test environments |
SASL_SSL | Yes | Yes | Confluent Cloud, MSK, Aiven, production |
- PLAINTEXT (development)
- SSL (TLS only)
- SASL_SSL (production)
GET SECRET and non-sensitive values like hostnames with GET ENV. See Environment Variables and Secrets for setup across Windows, Linux, Docker, and Kubernetes.Events and Direction
EachADD EVENT block maps one MQTT topic to one Kafka topic and sets the direction of flow. Think of the broker as the source side and Kafka as the destination side.
DIRECTION | SOURCE_TOPIC | DESTINATION_TOPIC | Data flow |
|---|---|---|---|
"out" | Broker MQTT topic (wildcards OK) | Kafka topic to produce to | MQTT → Kafka |
"in" | Kafka topic to subscribe to | Broker MQTT topic to publish to | Kafka → MQTT |
Event Parameters
Required
Required
DIRECTION is "out"; Kafka topic to subscribe to when DIRECTION is "in".DIRECTION is "out"; broker MQTT publish topic when DIRECTION is "in"."out" (MQTT → Kafka) or "in" (Kafka → MQTT).Optional
Optional
Message Keys and Partitioning
Kafka sends records with the same key to the same partition, which preserves order per key. On produce events, set the key withWITH QUERY.
- With a key (
WITH QUERY): same key → same partition → ordering preserved per key (for example, all readings from one device stay in order). - Without a key: records spread across all partitions for higher throughput, with no per-key ordering guarantee.
- Consume events join the consumer group and have partitions assigned automatically — set a stable
GROUP_IDso offsets survive restarts.
Key Placeholders
TheWITH QUERY value is resolved before each record is sent. Supported placeholders:
| Placeholder | Description | Example result |
|---|---|---|
{topic.N} | Nth segment (1-based) of the source topic | pump-01 from plant/sensors/pump-01/reading |
{topic} | Full source topic string | plant/sensors/pump-01/reading |
{payload} | Message payload as a string | 42.5 |
{payload.json} | Full payload parsed as JSON | — |
{payload.json.field} | A JSON field from the payload | pump-01 from {"device_id":"pump-01","value":42} |
{timestamp} | ISO 8601 timestamp | 2026-06-12T10:30:45.123Z |
{env.NAME} | Environment variable value | value of NAME |
{secret.NAME} | Secret value | value of NAME |
Key from a topic segment
Use a wildcard position from the source topic as the key — here the device ID in the third segment:plant/sensors/pump-01/reading gets the key pump-01.
Key from a JSON field
When the identifier lives inside the payload, pull it from a JSON field instead:{"device_id":"pump-01","value":42}, the record key becomes pump-01.
Complete Examples
- Production (SASL_SSL)
- High-throughput telemetry
- Multiple topic mappings
- Confluent Cloud
- High availability
Performance Tuning
A few settings control the trade-off between throughput, latency, durability, and memory. Tune them to match each stream.Durability vs. throughput (produce)
ACKS decides how many replicas must confirm each record before it counts as sent:
ACKS | Behavior | Use for |
|---|---|---|
all | Wait for all in-sync replicas (most durable, lower throughput) | Mission-critical data |
1 | Wait for the partition leader only | High-rate telemetry |
0 | Don’t wait at all | Fire-and-forget metrics where loss is acceptable |
Batching and compression (produce)
Under burst load, many produces are in flight at once and Kafka groups them into shared batches. These settings shape that behavior:| Setting | Effect |
|---|---|
LINGER_MS "0" | Send immediately — lowest latency, smallest batches |
LINGER_MS "50" | Wait up to 50 ms to fill a batch — fewer, larger requests |
COMPRESSION_TYPE "lz4" | Compress batches — lower bandwidth at negligible CPU cost |
BATCH_SIZE "2097152" | Allow 2 MB batches — more messages per request |
Consume throughput
Each consumed message is committed individually for at-least-once delivery, which adds a short round-trip per message. For very high-rate consume topics, use one Kafka route per logical stream rather than stacking many consume events on a single route.Memory use (consume)
The route pre-fetches messages into a buffer while it processes. On high-volume topics with many partitions this buffer can grow large. Cap it withQUEUED_MAX_MESSAGES_KB (for example "4096" for 4 MB per partition) and bound fetch responses with FETCH_MAX_BYTES.
Watch for consume backpressure
When a consume route publishes into the broker, a busy MQTT subsystem (many subscribers, large payloads) can slow the consumer down. If you pair a high-rate consume topic with many subscribers, monitor consumer group lag to catch this early.Best Practices
Always set a stable GROUP_ID
Always set a stable GROUP_ID
Use GET SECRET for credentials
Use GET SECRET for credentials
Use SASL_SSL in production
Use SASL_SSL in production
PLAINTEXT for local development; encrypt and authenticate everything else.Set AUTO_OFFSET_RESET deliberately
Set AUTO_OFFSET_RESET deliberately
Key messages for per-device ordering
Key messages for per-device ordering
List multiple bootstrap brokers
List multiple bootstrap brokers
Monitor consumer group lag
Monitor consumer group lag
kafka-consumer-groups --describe --group <GROUP_ID> to watch for growing lag, which signals publish backpressure.Troubleshooting
Quick connection check
Quick connection check
$SYS/Coreflux/Command from any MQTT client:Cannot connect to the cluster
Cannot connect to the cluster
- Confirm the bootstrap address and port are correct.
- Make sure
SECURITY_PROTOCOLmatches the broker’s listener. - Check that the port (default
9092) isn’t blocked by a firewall. - Verify network reachability to the broker host.
Connects, but no messages flow
Connects, but no messages flow
| Where Coreflux runs | BROKER_ADDRESS |
|---|---|
| On the host | localhost:9092 |
| Same Docker network as Kafka | kafka:9092 |
Authentication or SASL errors
Authentication or SASL errors
- Confirm
SECURITY_PROTOCOLmatches the listener (e.g.SASL_SSL, notSASL_PLAINTEXT). - Make sure
SASL_MECHANISMmatches what the broker requires. - Check that credentials are correct and the env/secret names resolve.
Consumer receives nothing / replays every restart
Consumer receives nothing / replays every restart
- Set
AUTO_OFFSET_RESET "Earliest"if messages were produced before the consumer first started. - Set a stable
GROUP_IDso offsets are remembered across restarts. - Give each route its own
GROUP_IDunless you intentionally want them to share partitions.
Performance problems
Performance problems
| Symptom | Likely cause | Fix |
|---|---|---|
| Produce slower than expected | ACKS "all" on a high-rate stream | Use ACKS "1" for telemetry |
| High bandwidth usage | No compression | Add COMPRESSION_TYPE "lz4" and LINGER_MS "50" |
| High memory on consume routes | Large prefetch buffer | Set QUEUED_MAX_MESSAGES_KB "4096" |
| Growing consumer lag | MQTT publish backpressure | Reduce subscriber load on the destination topics |
| Messages lost on shutdown | Flush timeout too short | Raise FLUSH_TIMEOUT_MS |

