Learn Java Kafka In Action Part 006 Producer Delivery Semantics
title: Learn Java Kafka in Action - Part 006 description: Production-grade guide to Kafka producer reliability and delivery semantics: acks, retries, idempotence, ordering, timeouts, transactions, fencing, and failure reasoning. series: learn-java-kafka-in-action seriesTitle: Learn Java Kafka in Action order: 6 partTitle: Producer Reliability and Delivery Semantics tags:
- java
- kafka
- producer
- delivery-semantics
- idempotence
- transactions
- reliability
- series date: 2026-07-01
Part 006 — Producer Reliability and Delivery Semantics
1. Tujuan Part Ini
Part ini membahas pertanyaan yang sering terlihat sederhana tetapi sebenarnya menentukan correctness sistem:
Ketika aplikasi Java memanggil
producer.send(), kapan kita boleh percaya bahwa event benar-benar tersimpan, tidak hilang, tidak terduplikasi, dan tetap berurutan?
Jawaban pendeknya: tergantung konfigurasi, failure mode, key/partition, broker durability, retry, idempotence, transaction, dan cara aplikasi menangani error.
Setelah part ini, kita harus bisa:
- Membedakan at-most-once, at-least-once, effectively-once, idempotent write, dan transactional write.
- Menjelaskan efek
acks=0,acks=1, danacks=all. - Memahami hubungan
acks,retries,enable.idempotence,max.in.flight.requests.per.connection,delivery.timeout.ms, danrequest.timeout.ms. - Menentukan config producer untuk event critical vs telemetry.
- Menjelaskan kapan duplicate bisa terjadi.
- Menjelaskan kapan ordering bisa rusak.
- Menggunakan transactional producer dengan benar.
- Menghindari klaim “exactly once” yang terlalu luas.
2. Delivery Semantics: Vocabulary yang Harus Rapi
Banyak bug Kafka berasal dari istilah yang dipakai longgar.
| Istilah | Makna Praktis | Catatan |
|---|---|---|
| At-most-once | Record diproses/kirim maksimal sekali | Bisa hilang |
| At-least-once | Record tidak hilang jika retry berhasil | Bisa duplikat |
| Exactly-once producer write | Retry producer tidak membuat duplicate di partition untuk producer session tertentu | Bukan end-to-end business exactly-once |
| Effectively-once | Hasil bisnis tampak sekali karena idempotency/dedup | Butuh desain aplikasi |
| Transactional write | Beberapa write Kafka dan/atau offset send dibuat atomic dalam transaksi Kafka | Terbatas pada boundary Kafka transaction |
Rule:
Kafka bisa membantu reliability, tetapi correctness bisnis tetap tanggung jawab desain aplikasi.
Contoh: producer idempotent bisa mencegah duplicate batch akibat retry producer. Tetapi jika API caller memanggil endpoint POST /orders/123/submit dua kali dan aplikasi membuat dua event berbeda, Kafka tidak tahu bahwa itu duplicate bisnis.
3. Delivery Pipeline
Titik failure:
- App crash sebelum
send(). - Serialization gagal.
- Buffer penuh.
- Metadata tidak tersedia.
- Request timeout.
- Broker leader crash sebelum append.
- Leader append sukses tetapi response hilang.
- Follower tidak cukup in-sync.
- Producer retry mengirim ulang.
- Callback gagal diamati aplikasi.
Delivery semantics adalah hasil gabungan dari semua titik ini.
4. acks: Kapan Broker Menganggap Write Sukses
acks menentukan kriteria broker sebelum mengirim response sukses ke producer.
acks | Broker Response Setelah | Kelebihan | Risiko |
|---|---|---|---|
0 | Producer tidak menunggu response | Latency paling rendah | Producer tidak tahu gagal; data bisa hilang |
1 | Leader menulis record | Lebih cepat dari all | Jika leader crash sebelum replication, data bisa hilang |
all / -1 | Leader menunggu ISR sesuai durability config | Durability terbaik | Latency lebih tinggi; bisa gagal jika ISR tidak cukup |
Untuk event bisnis penting, default engineering stance:
acks=all
Namun acks=all sendiri belum cukup. Ia harus dipasangkan dengan broker/topic durability config seperti:
replication.factor=3
min.insync.replicas=2
unclean.leader.election.enable=false
Durability equation:
Durable write ≈ replication.factor >= 3
+ min.insync.replicas >= 2
+ producer acks=all
+ unclean leader election disabled
+ disk/network capacity sehat
+ application observes send failure
Jika aplikasi mengabaikan callback error, acks=all tidak menyelamatkan correctness.
5. retries: Mengulang Request Tidak Sama dengan Aman
Producer retry berguna untuk error transient:
- Leader election.
- Network glitch.
- Temporary broker overload.
- Not enough replicas sementara.
- Request timeout yang masih bisa dipulihkan.
Tetapi retry punya risiko duplicate jika producer tidak idempotent.
Failure klasik:
Dari sisi producer, request pertama terlihat gagal. Dari sisi broker, record pertama sudah masuk. Jika producer retry tanpa idempotence, duplicate bisa muncul.
6. Idempotent Producer
Idempotent producer membuat retry producer aman terhadap duplicate write pada partition yang sama, selama berada dalam boundary yang didukung Kafka.
Konsep internal:
- Producer mendapatkan producer id.
- Record batch memiliki sequence number per partition.
- Broker menolak batch dengan sequence number yang tidak sesuai.
- Retry dari batch yang sama tidak menghasilkan duplicate append.
Config modern producer umumnya:
enable.idempotence=true
acks=all
retries=2147483647
max.in.flight.requests.per.connection=5
Important nuance:
Idempotent producer mencegah duplicate akibat retry internal producer. Ia tidak mencegah duplicate akibat aplikasi membuat event yang sama dua kali dengan event id berbeda.
7. Config Compatibility untuk Idempotence
Idempotence membutuhkan kombinasi config yang kompatibel.
| Config | Requirement / Rationale |
|---|---|
enable.idempotence=true | Mengaktifkan sequence-based duplicate protection |
acks=all | Broker harus memastikan durable append ke ISR |
retries > 0 | Idempotence berguna bersama retry |
max.in.flight.requests.per.connection <= 5 | Menjaga ordering/sequence guarantee dalam batas Kafka |
Jika config bertentangan, Kafka client modern dapat men-disable idempotence jika tidak eksplisit, atau melempar config exception jika idempotence eksplisit diaktifkan.
Baseline aman untuk event penting:
enable.idempotence=true
acks=all
retries=2147483647
max.in.flight.requests.per.connection=5
delivery.timeout.ms=120000
request.timeout.ms=30000
8. Ordering dan max.in.flight.requests.per.connection
Kafka hanya menjamin ordering dalam satu partition. Tetapi producer config bisa merusak ordering jika retry dan in-flight request tidak dikendalikan.
Failure tanpa idempotence:
Hasil log bisa menjadi:
Batch B
Batch A
Padahal aplikasi mengirim A sebelum B.
Dengan idempotence, broker menggunakan sequence number untuk menjaga order dalam partition sesuai batas protocol.
Rule:
Jika ordering per aggregate penting, gunakan key yang stabil dan idempotent producer. Jangan hanya mengandalkan “producer mengirim berurutan”.
9. Timeout Semantics
Timeout producer sering disalahpahami.
| Config | Arti |
|---|---|
request.timeout.ms | Batas menunggu response untuk satu request sebelum dianggap perlu retry/fail |
delivery.timeout.ms | Batas total waktu record sejak send sampai sukses/gagal final |
max.block.ms | Batas blocking di send() saat metadata/buffer tidak tersedia |
linger.ms | Waktu sengaja menunggu untuk batching |
transaction.timeout.ms | Batas transaksi terbuka sebelum coordinator abort |
Important:
request.timeout.ms < delivery.timeout.ms
Jika delivery.timeout.ms terlalu kecil, producer bisa gagal sebelum retry cukup. Jika terlalu besar, aplikasi terlalu lama menunggu failure signal.
Untuk event critical, timeout harus disejajarkan dengan:
- SLA endpoint.
- Retry policy aplikasi.
- Circuit breaker.
- Broker election time.
- Network latency.
- Observability alert threshold.
10. send() Return Success Bukan Berarti Business Success
Producer success berarti broker menerima record sesuai config. Ia tidak berarti:
- Consumer sudah memproses.
- Downstream DB sudah update.
- Event sesuai schema bisnis.
- Workflow selesai.
- Tidak ada duplicate bisnis.
- Semua region menerima event.
Jangan menulis API seperti ini tanpa clarity:
public SubmitOrderResponse submit(SubmitOrderCommand command) {
producer.send(toRecord(command));
return SubmitOrderResponse.success();
}
Pertanyaan design:
- Apakah response success berarti command diterima, event tersimpan, atau order benar-benar submitted?
- Apakah caller perlu event id untuk tracking?
- Apa yang terjadi jika send gagal setelah DB commit?
- Apa yang terjadi jika send sukses tetapi caller timeout?
Untuk command critical, outbox pattern sering lebih defensible daripada direct producer send dari request thread. Itu akan dibahas lebih dalam di Part 015 dan Part 027.
11. Delivery Profiles
11.1 Critical Business Event
Contoh:
OrderSubmittedPaymentCapturedCaseEscalatedEnforcementNoticeIssued
Config stance:
acks=all
enable.idempotence=true
retries=2147483647
max.in.flight.requests.per.connection=5
delivery.timeout.ms=120000
request.timeout.ms=30000
compression.type=zstd
Application stance:
- Observe callback/future.
- Use stable event id.
- Use stable aggregate key.
- Persist source-of-truth before publish or use outbox.
- Downstream idempotency required.
- Alert on send failure.
11.2 Telemetry / Metrics Event
Contoh:
- Clickstream low value.
- Debug metric.
- High-volume non-critical trace event.
Possible stance:
acks=1
enable.idempotence=false
retries=3
linger.ms=50
compression.type=lz4
Tetapi jangan copy ini ke event bisnis. Low durability config hanya boleh dipakai jika kehilangan data dapat diterima.
11.3 Audit Event
Audit event butuh perhatian khusus.
Config stance mirip critical event, tetapi design stance lebih ketat:
- Event id wajib.
- Actor wajib.
- Timestamp source wajib.
- Causation/correlation wajib.
- Schema compatibility ketat.
- Retention sesuai regulasi.
- Publish failure tidak boleh silent.
- Immutable audit log harus punya reconciliation.
Kafka bisa menjadi bagian audit pipeline, tetapi jangan klaim audit defensible tanpa retention, access control, schema governance, replay policy, dan reconciliation.
12. Handling Producer Result di Java
12.1 Fire-and-Forget: Hindari untuk Event Penting
producer.send(record);
Ini hanya aman untuk data yang boleh hilang atau jika ada observability lain yang menangkap failure. Untuk event bisnis penting, ini anti-pattern.
12.2 Callback
producer.send(record, (metadata, exception) -> {
if (exception != null) {
log.warn("Kafka publish failed topic={} key={}", record.topic(), record.key(), exception);
metrics.increment("kafka.publish.failure", "topic", record.topic());
return;
}
metrics.increment("kafka.publish.success", "topic", metadata.topic());
log.debug(
"Kafka publish success topic={} partition={} offset={}",
metadata.topic(),
metadata.partition(),
metadata.offset()
);
});
12.3 Future Bridge
public CompletableFuture<RecordMetadata> publish(OrderEvent event) {
ProducerRecord<String, OrderEvent> record = new ProducerRecord<>(
"order-events",
event.orderId(),
event
);
CompletableFuture<RecordMetadata> future = new CompletableFuture<>();
producer.send(record, (metadata, exception) -> {
if (exception != null) {
future.completeExceptionally(exception);
} else {
future.complete(metadata);
}
});
return future;
}
12.4 Synchronous Wait: Pakai dengan Hati-Hati
RecordMetadata metadata = producer
.send(record)
.get(5, TimeUnit.SECONDS);
Berguna untuk:
- CLI/admin tool.
- Test.
- Startup validation.
- Low-throughput critical path dengan SLA jelas.
Berbahaya untuk:
- High-throughput request path.
- Callback thread.
- Event loop/reactive thread.
13. Error Classification
Producer exception harus diklasifikasi.
| Error Type | Contoh | Bias Tindakan |
|---|---|---|
| Retriable transient | Temporary leader unavailable, network glitch | Internal retry producer atau retry aplikasi dengan backoff |
| Authorization/config | Topic authorization failed, invalid config | Fail fast, alert platform |
| Serialization | Invalid payload/schema | Bug aplikasi atau schema mismatch |
| Timeout | Delivery timeout, request timeout | Ambiguous: bisa sudah tertulis atau belum |
| Fencing | Producer fenced | Instance duplicate/zombie; stop producer |
| Record too large | Message exceeds limit | Fix payload design/config |
Important timeout nuance:
Saat producer menerima timeout, status record bisa ambiguous. Jangan otomatis membuat side effect lain yang mengasumsikan record pasti tidak tertulis.
Dengan idempotent producer, retry internal mengurangi duplicate karena ambiguous response. Tetapi jika aplikasi membuat record baru dengan event id baru setelah timeout, duplicate bisnis masih bisa terjadi.
14. Transactional Producer
Transactional producer dipakai ketika kita perlu atomicity dalam boundary Kafka.
Use case utama:
- Consume-transform-produce dengan offset commit atomic ke Kafka.
- Menulis ke beberapa topic/partition secara atomic.
- Kafka Streams exactly-once processing.
Bukan solusi langsung untuk:
- Atomic commit antara PostgreSQL dan Kafka tanpa pattern tambahan.
- Exactly-once side effect ke REST API eksternal.
- Menghilangkan kebutuhan idempotent consumer.
14.1 Transactional Config
transactional.id=order-transformer-0
enable.idempotence=true
acks=all
retries=2147483647
max.in.flight.requests.per.connection=5
transaction.timeout.ms=60000
transactional.id harus stabil untuk logical producer instance, tetapi tidak boleh dipakai bersamaan oleh dua instance aktif. Jika dua producer memakai transactional.id yang sama, producer lama/zombie bisa difence.
14.2 Transaction API
producer.initTransactions();
while (running) {
ConsumerRecords<String, OrderEvent> records = consumer.poll(Duration.ofMillis(500));
if (records.isEmpty()) {
continue;
}
try {
producer.beginTransaction();
for (ConsumerRecord<String, OrderEvent> record : records) {
ProjectionEvent output = transform(record.value());
producer.send(new ProducerRecord<>(
"order-projection-events",
record.key(),
output
));
}
Map<TopicPartition, OffsetAndMetadata> offsets = offsetsToCommit(records);
producer.sendOffsetsToTransaction(offsets, consumer.groupMetadata());
producer.commitTransaction();
} catch (ProducerFencedException | OutOfOrderSequenceException | AuthorizationException fatal) {
producer.close();
throw fatal;
} catch (KafkaException e) {
producer.abortTransaction();
}
}
Consumer yang membaca output transactional harus memakai:
isolation.level=read_committed
Jika tidak, consumer bisa melihat record yang nanti diabort.
15. Producer Fencing
Producer fencing mencegah zombie producer menulis setelah instance pengganti mengambil alih transactional identity.
Scenario:
Implication:
- Fenced producer harus berhenti.
- Jangan catch lalu retry seolah transient biasa.
- Di Kubernetes, pastikan transactional id tidak dipakai dua pod aktif kecuali memang ingin fencing.
16. Transaction Boundary Caveat: DB + Kafka
Misal:
@Transactional
public void submitOrder(SubmitOrderCommand command) {
orderRepository.save(order);
producer.send(orderSubmittedRecord).get();
}
Ini tidak membuat PostgreSQL dan Kafka menjadi satu distributed transaction.
Failure matrix:
| DB Commit | Kafka Send | Result |
|---|---|---|
| Fail | Not sent | Safe fail |
| Success | Success | Good |
| Success | Fail | DB updated, event missing |
| Unknown | Unknown | Hard reconciliation |
Alternatif umum:
- Transactional outbox.
- CDC from outbox table.
- Idempotent publisher.
- Reconciliation job.
- Clear command status state.
Kafka transaction tidak otomatis menyelesaikan atomicity dengan database eksternal.
17. Event ID dan Idempotency Key
Setiap event bisnis penting harus punya event id.
{
"eventId": "01JZ6R5A9AG6Z7G2T7V9H0R2EY",
"eventType": "OrderSubmitted",
"aggregateType": "Order",
"aggregateId": "ORD-123",
"occurredAt": "2026-07-01T10:15:30Z",
"payload": {
"orderId": "ORD-123",
"customerId": "CUST-9"
}
}
Producer idempotence memakai sequence internal. Business idempotency memakai event id.
Rule:
Jangan mengandalkan Kafka offset sebagai event id bisnis. Offset berubah antar topic, partition, replay pipeline, dan environment.
18. Send Failure Strategy
Saat publish gagal, pilihan kita:
| Strategy | Cocok Untuk | Risiko |
|---|---|---|
| Fail request | Synchronous command yang butuh publish before success | Latency, ambiguous timeout |
| Store outbox | Critical business event | Butuh publisher/reconciliation |
| Drop | Telemetry low-value | Data loss accepted |
| Local retry queue | Short transient outage | Memory loss jika process crash |
| Dead-letter publish failure | Invalid event after serialization/design issue | Bisa recursive jika Kafka unavailable |
Untuk event critical, pattern paling defensible biasanya:
Write business state + outbox in DB transaction
Async publisher reads outbox
Publisher sends to Kafka with idempotent producer
Mark outbox published after ack
Reconciliation checks stuck outbox rows
19. Practical Config Profiles
19.1 Safe Business Producer
bootstrap.servers=kafka-1:9092,kafka-2:9092,kafka-3:9092
client.id=order-service-business-producer
key.serializer=org.apache.kafka.common.serialization.StringSerializer
value.serializer=com.example.kafka.OrderEventSerializer
acks=all
enable.idempotence=true
retries=2147483647
max.in.flight.requests.per.connection=5
delivery.timeout.ms=120000
request.timeout.ms=30000
max.block.ms=60000
linger.ms=5
batch.size=32768
compression.type=zstd
19.2 Low-Latency Producer with Some Durability
client.id=notification-service-producer
acks=1
enable.idempotence=true
retries=10
delivery.timeout.ms=30000
request.timeout.ms=10000
linger.ms=0
compression.type=lz4
Catatan: acks=1 dengan idempotence bisa menjadi konflik tergantung versi/config karena idempotence membutuhkan acks=all. Jangan aktifkan kombinasi ini tanpa validasi. Jika idempotence wajib, gunakan acks=all.
19.3 High-Volume Telemetry Producer
client.id=telemetry-producer
acks=1
enable.idempotence=false
retries=3
linger.ms=50
batch.size=65536
compression.type=lz4
delivery.timeout.ms=30000
Hanya gunakan jika kehilangan sebagian event diterima secara bisnis.
20. Testing Producer Semantics
20.1 Unit Test Tidak Cukup
Mock producer bisa memvalidasi bahwa code memanggil send(), tetapi tidak membuktikan:
- Retry behavior.
- Idempotence.
- Ordering saat broker failure.
- Timeout semantics.
- Transaction abort visibility.
Gunakan integration test dengan broker nyata.
20.2 Test Cases
| Test | Cara | Expected |
|---|---|---|
| Send success | Produce record, consume back | Metadata valid |
| Serialization failure | Payload invalid | Future/caller gagal, tidak silent |
| Broker unavailable | Stop broker leader | Retry/failure sesuai timeout |
| Duplicate retry | Simulate response loss jika mungkin | Tidak duplicate dengan idempotence |
| Transaction abort | Begin, send, abort | Consumer read_committed tidak melihat record |
| Fencing | Dua producer same transactional.id | Producer lama fenced |
20.3 Property to Assert
Untuk event critical:
For each business event id, downstream materialized state must apply it at most once.
Ini bukan hanya producer test; ini test end-to-end idempotency.
21. Observability untuk Delivery Semantics
Metrics penting:
| Metric | Kenapa Penting |
|---|---|
record-error-rate | Publish gagal |
record-retry-rate | Broker/network tidak stabil |
request-latency-avg/max | Broker/network latency |
record-send-rate | Throughput |
buffer-available-bytes | Backpressure producer |
batch-size-avg | Batching efektif atau tidak |
outgoing-byte-rate | Network pressure |
| Transaction abort count | EOS/transaction instability |
Log minimal saat failure:
eventId=01JZ6R5A9AG6Z7G2T7V9H0R2EY
eventType=OrderSubmitted
aggregateId=ORD-123
topic=order-events
key=ORD-123
clientId=order-service-business-producer
exception=TimeoutException
Alert:
- Send error rate > 0 untuk critical topic.
- Retry rate spike.
- Delivery timeout spike.
- Producer buffer exhaustion.
- Transaction abort/fencing unexpected.
22. Decision Matrix
| Requirement | Recommended Producer Strategy |
|---|---|
| Must not lose accepted business command | Outbox + idempotent producer + reconciliation |
| Must preserve order per aggregate | Key by aggregate id + idempotent producer |
| Can tolerate duplicate downstream but not loss | At-least-once + idempotent consumer |
| Can tolerate loss for low-value telemetry | Lower acks/retries, high batching |
| Consume-process-produce atomically in Kafka | Transactional producer + sendOffsetsToTransaction |
| DB and Kafka atomicity required | Outbox/CDC, not Kafka transaction alone |
| Multi-topic atomic Kafka write | Transactional producer |
| Regulatory audit trail | Strong producer config + immutable event id + retention/security/governance |
23. Failure Reasoning Examples
23.1 Leader Crash After Append Before Response
Question:
Producer gets timeout. Did the event get written?
Answer:
Maybe.
If leader appended record but response was lost, record may exist. Producer retry with idempotence should not duplicate. Application-level retry with new event id can duplicate business event.
23.2 acks=1, Leader Crash Before Follower Replication
Question:
Producer got success. Can the event still disappear?
Answer:
Yes. If only leader had the record and leader crashed before followers replicated it, a new leader without the record can be elected, depending cluster state and election policy.
23.3 acks=all, ISR Too Small
Question:
Why did producer fail when broker is still up?
Answer:
If min.insync.replicas=2 and ISR drops to 1, broker rejects writes with not-enough-replicas behavior. This is correct: Kafka is refusing to acknowledge a write that does not meet durability requirement.
23.4 Duplicate Event Despite Idempotent Producer
Question:
Idempotence is enabled. Why did downstream see duplicate order submitted?
Possible reasons:
- Application produced same business event twice with different event id.
- Two service instances handled same command.
- Outbox publisher did not mark row and republished with new event id.
- Consumer applied event twice because downstream idempotency missing.
- Different producers produced semantically same event.
Idempotent producer is not business deduplication.
24. Mini Lab
24.1 Build Three Producer Profiles
Create:
BusinessEventProducerConfigTelemetryProducerConfigTransactionalTransformerProducerConfig
Each must explicitly set:
client.idacksenable.idempotenceretriesdelivery.timeout.msrequest.timeout.msmax.in.flight.requests.per.connection- Serializer classes
24.2 Simulate Failure
Run local Kafka, then:
- Produce 1000 events.
- Kill broker leader mid-send.
- Observe retry and final send result.
- Verify consumed event ids are unique.
- Repeat with idempotence disabled.
24.3 Transaction Visibility Test
- Create transactional producer.
- Begin transaction.
- Send 10 records.
- Abort transaction.
- Consume with
read_committed. - Consume with
read_uncommitted. - Compare visibility.
25. Design Review Checklist
Producer Config
- Is
acksexplicitly set? - Is idempotence enabled for critical events?
- Are retries and timeout configured intentionally?
- Is
max.in.flight.requests.per.connectioncompatible with ordering/idempotence? - Is
delivery.timeout.msaligned with SLA? - Is
compression.typeselected deliberately?
Application Semantics
- Does every critical event have
eventId? - Is key aligned with ordering boundary?
- Does application observe send failure?
- Is timeout treated as ambiguous?
- Is downstream idempotent?
- Is there an outbox/reconciliation path if DB state and Kafka publish must not diverge?
Transactional Producer
- Is
transactional.idstable and unique per logical instance? - Are fatal exceptions treated as fatal?
- Do output consumers use
read_committedif needed? - Is transaction duration below
transaction.timeout.ms? - Is DB/Kafka atomicity not falsely assumed?
26. Interview-Level Questions
- Why can
acks=1return success and still lose data later? - What does idempotent producer protect against?
- What does idempotent producer not protect against?
- Why can producer timeout be ambiguous?
- Why does idempotence require compatible
acks, retries, and in-flight settings? - What happens when two producers use the same
transactional.id? - Why is Kafka transaction not enough for DB + Kafka atomicity?
- What is the difference between producer idempotence and consumer idempotency?
- Why should critical events have business event ids?
- When is
acks=0acceptable?
27. Ringkasan
Producer reliability bukan satu config. Ia adalah kombinasi antara broker durability, producer acknowledgement, retry, idempotence, ordering boundary, timeout, transaction, dan application-level handling.
Untuk event bisnis penting, stance default adalah acks=all, idempotence enabled, retries tinggi, timeout jelas, stable key, event id, callback/future observed, dan downstream idempotency. Untuk atomicity antara database dan Kafka, gunakan pattern seperti outbox/CDC; jangan menganggap Kafka transaction menyelesaikan distributed transaction eksternal.
Transactional producer kuat untuk atomic Kafka write dan consume-process-produce flow, tetapi membutuhkan transactional.id, fencing awareness, abort handling, dan consumer read_committed jika output aborted tidak boleh terlihat.
Part berikutnya akan membahas Producer Throughput, Batching, and Compression: bagaimana mencapai throughput tinggi tanpa merusak latency, memory, ordering, dan reliability.
28. Referensi
- Apache Kafka Documentation — Producer configs and message delivery semantics.
- Apache Kafka Producer Configs —
acks,enable.idempotence, retries, timeout, in-flight requests. - Apache Kafka Javadocs —
KafkaProducerand transactions. - Confluent Documentation — Message delivery guarantees and transactions.
- Confluent Pattern Catalog — Idempotent Writer.
You just completed lesson 06 in start here. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.
Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.