Working with Kafka in Swift (iOS/macOS)
Apache Kafka is a distributed data streaming platform widely used in microservice architecture, real-time analytics, and messaging systems. For iOS/macOS developers, integrating Kafka may be necessary when creating applications that process real-time events, work with IoT devices, or interact with a Java/Go backend. In this article, we will review the main libraries for working with Kafka in Swift, how to connect them, and code examples.
Why is Kafka needed in mobile/desktop applications?
Although Kafka is more often associated with the server side, there are scenarios where client applications interact directly with brokers:
- Logging and analytics: sending application usage events to the server.
- Chat and notifications: receiving real-time messages via Kafka instead of WebSocket.
- Data synchronization: updating local data when changes occur in a distributed system.
- IoT and sensors: transmitting data from a device to the server via Kafka.
Main libraries for Swift
Currently, there are several mature solutions for working with Kafka in Swift:
- SwiftLiteKafka — a lightweight C wrapper for librdkafka, supports iOS and macOS.
- Perfect-Kafka — part of the Perfect ecosystem, focused on server-side Swift (macOS/Linux), but can be adapted for clients.
- KafkaSwift — a pure Swift implementation (no C dependencies), but with limited performance.
The most stable and performant is considered to be SwiftLiteKafka, so we will focus on it further.
Installing SwiftLiteKafka
The library is distributed via Swift Package Manager. Add the dependency in Package.swift or via Xcode:
// Package.swiftdependencies: [ .package(url: "https://github.com/swift-server/swift-lite-kafka.git", from: "1.0.0")]For iOS, you also need to enable support for the C library librdkafka — it is automatically pulled in as a dependency.
Basic example: Producer (sending messages)
Let's create a simple producer that sends a string to the topic "test-topic":
import SwiftLiteKafka
let config = KafkaConfig()config.bootstrapServers = "localhost:9092"
let producer = try KafkaProducer(config: config)defer { producer.close() }
let message = KafkaMessage( value: "Hello from Swift!".data(using: .utf8)!, key: "key1".data(using: .utf8))
try producer.send(message, to: "test-topic")print("Message sent")Note: send is a synchronous call. For asynchronous sending, use callbacks or async/await (Swift 5.5+).
Basic example: Consumer (reading messages)
Example of subscribing to a topic and reading messages in a loop:
import SwiftLiteKafka
let config = KafkaConfig()config.bootstrapServers = "localhost:9092"config.groupId = "swift-consumer-group"
let consumer = try KafkaConsumer(config: config)consumer.subscribe(topics: ["test-topic"])
while true { let message = try consumer.poll(timeout: .seconds(1)) if let msg = message { let value = String(data: msg.value, encoding: .utf8) ?? "nil" print("Received: \\(value)") }}For real applications, it is recommended to use async/await or Combine to avoid blocking the main thread.
Advanced features
- SSL/TLS: configuring encryption via
KafkaConfig(propertiessecurityProtocol,sslCACertificat