A common question when designing event-driven systems with Apache Kafka is how to guarantee that messages are processed in the exact order they were produced.
Partition-Level Ordering Guarantee
Kafka guarantees strict message ordering only within a single partition, not across all partitions of a topic. If order matters for a specific entity (such as user transactions or account updates), all records for that entity must be routed to the same partition.
Using Message Keys
By specifying a key when producing records, Kafka's default partitioner hashes the key to consistently assign it to the same partition index.
ProducerRecord<String, String> record = new ProducerRecord<>(
"account-transactions",
"account-12345",
"{\"amount\": 250.00, \"type\": \"DEPOSIT\"}"
);
producer.send(record, (metadata, exception) -> {
if (exception == null) {
System.out.println("Message sent to partition: " + metadata.partition());
} else {
exception.printStackTrace();
}
});Key Considerations for Ordering
- Max In-Flight Requests: Ensure
max.in.flight.requests.per.connection=1or enable idempotence (enable.idempotence=true) to prevent message reordering during retries. - Partition Count Changes: Adding partitions to an existing topic will change key hashing distribution, potentially routing existing keys to new partitions.