Series MapLesson 14 / 50
Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Build CoreOrdered learning track

Event Metadata and Traceability

Event ID, aggregate ID, correlation ID, causation ID, trace context, tenant, actor, source service, event type/version/time, schema version, partition key, command ID, idempotency key, headers vs payload, standardisasi metadata, auditability, dan traceability checklist.

17 min read3206 words
PrevNext
Lesson 1450 lesson track10–27 Build Core
#kafka#event-metadata#traceability#correlation-id+3 more

Part 014 — Event Metadata and Traceability

1. Tujuan Part Ini

Part ini membahas metadata event Kafka: data kecil yang membuat event bisa ditelusuri, di-debug, diaudit, di-deduplicate, di-replay, dan dikorelasikan dengan HTTP request, database transaction, outbox row, consumer processing, dan downstream workflow.

Payload menjawab:

Apa fakta bisnis yang terjadi?

Metadata menjawab:

Event ini dari mana?
Kenapa event ini ada?
Siapa yang memicu?
Kapan terjadi?
Versi contract apa yang dipakai?
Event ini bagian dari request/workflow yang mana?
Apakah event ini duplicate?
Bagaimana event ini ditelusuri saat incident?

Dalam sistem enterprise, metadata bukan dekorasi.

Metadata adalah control plane untuk event-driven debugging.

2. Core Mental Model

Kafka record memiliki struktur dasar:

topic + partition + offset + key + value + headers + timestamp

Namun sistem production biasanya membutuhkan envelope logis:

{
  "metadata": {
    "eventId": "evt-...",
    "eventType": "OrderSubmitted",
    "eventVersion": "1.0",
    "correlationId": "corr-...",
    "causationId": "cmd-...",
    "traceId": "trace-...",
    "tenantId": "tenant-...",
    "sourceService": "order-service",
    "eventTime": "2026-07-11T02:13:44Z"
  },
  "payload": {
    "orderId": "ORD-123",
    "status": "SUBMITTED"
  }
}

Atau metadata bisa disimpan di Kafka headers, dengan payload hanya berisi business data.

Yang penting bukan bentuk fisiknya.

Yang penting adalah metadata standard, konsisten, dan tersedia di producer, outbox, broker, consumer, logs, metrics, tracing, dan DLQ.

3. Metadata sebagai Debugging Surface

Tanpa metadata, incident Kafka sering menjadi teka-teki:

Ada event salah. Event ini dari request mana?
Siapa user-nya?
Service mana yang publish?
Apakah duplicate?
Apakah replay?
Apakah versi schema baru?
Consumer mana yang gagal?
Apakah event ini menyebabkan saga stuck?

Dengan metadata yang baik, pertanyaan berubah menjadi query:

Find logs by correlationId.
Find event by eventId.
Find outbox row by eventId.
Find trace by traceId.
Find consumer processing by eventId.
Find DLQ item by originalTopic + partition + offset.

Metadata mengubah debugging dari forensics manual menjadi traceable workflow.

4. Event ID

Event ID adalah unique identifier untuk satu event occurrence.

Fungsi utama:

  • deduplication
  • idempotency
  • audit trail
  • DLQ tracking
  • replay tracking
  • log correlation
  • consumer inbox key

Contoh:

{
  "eventId": "evt_01J2KQ4D6XG8Y8X2Z7G9G2NQEP"
}

Prinsip:

  • harus unik secara global atau cukup unik dalam scope event system
  • dibuat sekali saat event dibuat
  • tidak berubah saat retry publish
  • tidak berubah saat event masuk DLQ
  • tidak berubah saat replay, kecuali replay event memang diperlakukan sebagai event baru dengan metadata asal tetap disimpan

Anti-pattern:

Generate eventId setiap retry producer.

Akibat:

  • duplicate terlihat seperti event baru
  • consumer idempotency gagal
  • audit trail pecah

5. Aggregate ID

Aggregate ID adalah ID entity/domain aggregate yang menjadi subjek event.

Contoh:

  • quoteId
  • orderId
  • customerId
  • accountId
  • catalogItemId

Fungsi:

  • partition key candidate
  • ordering per aggregate
  • business traceability
  • projection update key
  • reconciliation key

Contoh:

{
  "aggregateType": "Order",
  "aggregateId": "ORD-123"
}

Jika event adalah domain event, aggregate ID biasanya wajib.

Jika event adalah integration event lintas domain, aggregate ID tetap harus jelas, meskipun mungkin ada beberapa ID bisnis.

6. Correlation ID

Correlation ID menghubungkan seluruh chain aktivitas yang berasal dari satu request, command, workflow, atau business interaction.

Contoh alur:

HTTP POST /orders
  correlationId = corr-123
    → outbox event OrderSubmitted correlationId=corr-123
      → billing consumer logs correlationId=corr-123
      → fulfillment command correlationId=corr-123
      → notification event correlationId=corr-123

Fungsi:

  • trace request lintas service
  • incident investigation
  • log aggregation
  • support/debugging
  • workflow correlation

Dalam JAX-RS service, correlation ID biasanya berasal dari:

  • incoming HTTP header
  • generated server-side jika tidak ada
  • gateway/API layer
  • workflow command
  • batch/replay job

Prinsip:

Correlation ID harus dipropagasikan, bukan dibuat ulang di setiap service.

7. Causation ID

Causation ID menjawab: event ini disebabkan oleh apa?

Contoh:

  • command ID
  • previous event ID
  • request ID
  • saga step ID
  • workflow task ID

Jika correlation ID menghubungkan satu keseluruhan journey, causation ID menghubungkan sebab langsung.

Contoh:

Command SubmitOrder cmd-001
  → Event OrderSubmitted evt-101 causationId=cmd-001
    → Event OrderValidated evt-102 causationId=evt-101
      → Command StartFulfillment cmd-201 causationId=evt-102

Causation chain sangat berguna untuk menganalisis event storm, loop, dan saga behavior.

Tanpa causation ID, sulit membedakan event pertama dari event turunan.

8. Trace ID dan Span Context

Trace ID menghubungkan event processing dengan distributed tracing.

Dalam sistem modern, trace context sering memakai W3C Trace Context:

traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01

Kafka event perlu membawa trace context agar trace dapat melewati boundary asynchronous.

Namun async tracing berbeda dari sync HTTP tracing.

Event bisa diproses:

  • beberapa detik kemudian
  • beberapa menit kemudian
  • beberapa kali akibat retry
  • oleh banyak consumer
  • saat replay jauh setelah request asli selesai

Karena itu, trace harus dipahami sebagai causal trace, bukan selalu satu request latency trace sederhana.

Prinsip:

  • producer menulis trace context ke header/metadata
  • consumer membaca trace context
  • consumer membuat span baru untuk processing
  • retry/replay diberi attribute yang jelas
  • DLQ publish mempertahankan original trace/correlation metadata

9. Tenant ID

Tenant ID penting untuk sistem multi-tenant.

Fungsi:

  • authorization context
  • data isolation
  • routing
  • observability per tenant
  • incident blast-radius analysis
  • rate limiting
  • compliance evidence

Prinsip:

Tenant ID di event harus berasal dari trusted context, bukan input bebas dari payload yang tidak divalidasi.

Risiko jika tenant ID hilang:

  • consumer tidak bisa enforce tenant boundary
  • logs tidak bisa difilter per tenant
  • replay bisa memproses data tenant secara salah
  • DLQ triage sulit

Risiko jika tenant ID salah:

  • cross-tenant data leak
  • projection salah tenant
  • compliance incident

10. Actor/User ID

Actor ID menjawab siapa atau apa yang memicu perubahan.

Actor bisa berupa:

  • end user
  • admin user
  • service account
  • batch job
  • system process
  • workflow engine
  • integration partner

Metadata sebaiknya membedakan:

{
  "actorType": "USER",
  "actorId": "usr-123"
}

atau:

{
  "actorType": "SERVICE",
  "actorId": "pricing-service"
}

Jangan menaruh informasi sensitif seperti email lengkap atau nama user di header jika tidak diperlukan.

Untuk audit, ID stabil biasanya lebih aman daripada data personal langsung.

11. Source Service

Source service adalah service yang menghasilkan event.

Contoh:

{
  "sourceService": "order-service",
  "sourceInstance": "order-service-7d9f8b9c4c-nx2la"
}

sourceService biasanya contract-level metadata.

sourceInstance lebih operational dan bisa masuk log/header, tidak selalu perlu menjadi payload contract.

Fungsi source service:

  • incident ownership
  • debugging producer version
  • routing audit
  • event catalog validation
  • detecting unexpected producer

Jika satu topic menerima event dari banyak producer, source service menjadi lebih penting.

Namun multi-producer topic harus direview dengan hati-hati karena ownership dan schema governance lebih kompleks.

12. Event Type

Event type menjelaskan jenis fakta bisnis.

Contoh:

  • QuoteCreated
  • QuoteSubmitted
  • OrderSubmitted
  • OrderCancelled
  • CatalogItemUpdated

Event type harus stabil dan meaningful.

Anti-pattern:

OrderEvent
DataChanged
NotificationEvent
MessageEvent

Nama generic membuat consumer harus membaca payload untuk memahami arti event.

Untuk topic yang berisi banyak event type, event type wajib.

Untuk topic-per-event, event type tetap berguna untuk logging, schema registry, DLQ, dan tracing.

13. Event Version

Event version menjelaskan versi semantic contract event.

Contoh:

{
  "eventType": "OrderSubmitted",
  "eventVersion": "1.1"
}

Event version tidak selalu sama dengan schema registry version.

Schema version bisa berubah karena optional field.

Event version sebaiknya berubah ketika semantic contract berubah.

Heuristik:

  • additive optional field: schema version naik, event version mungkin tetap
  • semantic meaning berubah: event version harus naik atau event type baru
  • breaking change: event version/topic/type baru + migration plan

14. Event Time

Event time adalah waktu ketika fakta bisnis terjadi.

Contoh:

{
  "eventTime": "2026-07-11T03:04:05Z"
}

Event time berbeda dari Kafka record timestamp dan processing time.

Contoh:

TimeArti
eventTimebusiness fact happened
publishedTimeproducer/outbox published to Kafka
broker timestamptimestamp pada Kafka record
consumedTimeconsumer menerima record
processingTimeconsumer memproses record

Dalam workflow bisnis, event time sering lebih penting daripada processing time.

Dalam observability latency, perbedaan waktu ini penting untuk menghitung lag end-to-end.

15. Processing Time

Processing time adalah waktu consumer memproses event.

Processing time biasanya bukan bagian dari original event contract.

Ini lebih cocok di log/metric/trace atau consumer-side audit.

Contoh log consumer:

{
  "eventId": "evt-123",
  "eventType": "OrderSubmitted",
  "consumerGroup": "billing-projection",
  "processingTime": "2026-07-11T03:04:08Z",
  "processingLatencyMs": 253
}

Jangan menimpa eventTime dengan processingTime.

Itu akan menghancurkan temporal reasoning.

16. Schema Version

Schema version atau schema ID membantu consumer memahami payload format.

Jika memakai Schema Registry, schema ID mungkin sudah ada dalam serialized payload atau metadata serializer.

Namun untuk observability, schema version/ID sering tetap perlu terlihat di logs.

Fungsi:

  • debugging deserialization failure
  • tracking rollout schema baru
  • DLQ analysis
  • compatibility verification
  • replay support

Contoh log:

{
  "eventType": "OrderSubmitted",
  "schemaSubject": "order-submitted-value",
  "schemaId": 1042,
  "schemaVersion": 7
}

17. Partition Key

Partition key adalah routing key Kafka.

Metadata harus menjelaskan key yang digunakan.

Contoh:

Kafka record key: ORD-123
metadata.partitionKey: ORD-123
metadata.partitionKeyType: orderId

Mengapa perlu dicatat?

  • debugging ordering issue
  • detecting key mismatch
  • hot partition analysis
  • replay verification
  • consumer state partitioning

Jika payload orderId = ORD-123, tetapi Kafka record key ternyata tenant-9, ordering per order tidak dijamin.

Metadata atau log harus membuat mismatch mudah terdeteksi.

18. Command ID

Command ID mengidentifikasi command/request yang memicu event.

Contoh:

{
  "commandId": "cmd-submit-order-123"
}

Fungsi:

  • idempotency dari command
  • causation tracking
  • duplicate command detection
  • linking HTTP request to event
  • saga command/reply correlation

Command ID berbeda dari event ID.

Satu command bisa menghasilkan beberapa event.

SubmitOrder command
  → OrderSubmitted event
  → OrderValidationRequested event
  → OrderAuditRecorded event

19. Idempotency Key

Idempotency key membantu mencegah double processing untuk command atau event tertentu.

Di HTTP/JAX-RS:

POST /orders
Idempotency-Key: idem-abc

Di event:

{
  "idempotencyKey": "idem-abc"
}

Namun event consumer biasanya lebih aman dedup berdasarkan eventId.

Idempotency key berguna jika event merupakan hasil command external dan downstream perlu tahu duplicate command boundary.

Jangan campuradukkan:

KeyFungsi
eventIdunique event occurrence
idempotencyKeyduplicate command/request prevention
aggregateIdbusiness entity identity
correlationIdjourney identity
causationIddirect cause identity
partitionKeyKafka routing/ordering key

20. Headers vs Payload

Pertanyaan umum:

Metadata taruh di Kafka headers atau payload envelope?

Jawabannya bergantung pada standard internal, tetapi trade-off-nya harus dipahami.

Kafka Headers

Kelebihan:

  • cocok untuk routing/observability metadata
  • tidak mencemari business payload
  • mudah dipakai interceptor/middleware
  • bisa dibaca tanpa deserialize full payload dalam beberapa tooling

Risiko:

  • tidak semua tooling menampilkan header dengan nyaman
  • schema governance header sering lebih lemah
  • header bisa hilang jika connector/bridge tidak preserve
  • consumer bisa lupa membaca header

Payload Envelope

Kelebihan:

  • metadata ikut schema
  • mudah diaudit bersama payload
  • mudah direplay dari storage
  • cocok untuk event log canonical

Risiko:

  • payload lebih verbose
  • business schema bercampur envelope
  • perubahan envelope memengaruhi semua event

Hybrid

Banyak sistem memakai hybrid:

  • header untuk trace/correlation/routing operational metadata
  • payload envelope untuk eventId/eventType/eventVersion/eventTime/sourceService

Yang terpenting: standard harus konsisten.

21. Metadata Standardization

Metadata harus distandardisasi lintas producer dan consumer.

Contoh standard minimal:

required:
  - eventId
  - eventType
  - eventVersion
  - sourceService
  - eventTime
  - correlationId
  - aggregateId
  - partitionKey
recommended:
  - causationId
  - traceparent
  - tenantId
  - actorType
  - actorId
  - commandId
  - idempotencyKey
  - schemaVersion
  - producerVersion

Jangan biarkan setiap service membuat nama sendiri:

corrId
correlation_id
correlationId
x-correlation-id
requestCorrelation

Perbedaan kecil seperti ini membuat log query dan tracing sulit.

22. Metadata Propagation dari JAX-RS

Dalam Java/JAX-RS service, metadata biasanya dibuat atau dibaca di boundary request.

Flow umum:

flowchart LR A[HTTP Request] --> B[JAX-RS Filter] B --> C[Request Context] C --> D[Service Layer] D --> E[DB Transaction] E --> F[Outbox Row] F --> G[Kafka Producer] G --> H[Kafka Topic] H --> I[Consumer]

JAX-RS filter bisa:

  • membaca X-Correlation-ID
  • generate correlation ID jika kosong
  • membaca trace context
  • membaca tenant/user context dari auth layer
  • menyimpan context ke request-scoped object

Service layer kemudian memakai context tersebut saat membuat event metadata.

Prinsip:

Resource method tidak boleh membuat metadata secara ad hoc tanpa standard.

23. Outbox Metadata

Jika memakai outbox pattern, metadata harus disimpan di outbox row.

Contoh schema outbox:

CREATE TABLE outbox_event (
    id UUID PRIMARY KEY,
    event_id TEXT NOT NULL UNIQUE,
    event_type TEXT NOT NULL,
    event_version TEXT NOT NULL,
    aggregate_type TEXT NOT NULL,
    aggregate_id TEXT NOT NULL,
    partition_key TEXT NOT NULL,
    correlation_id TEXT,
    causation_id TEXT,
    traceparent TEXT,
    tenant_id TEXT,
    source_service TEXT NOT NULL,
    event_time TIMESTAMPTZ NOT NULL,
    payload JSONB NOT NULL,
    headers JSONB,
    status TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

Outbox metadata membantu:

  • publish retry tanpa kehilangan event ID
  • debug event sebelum masuk Kafka
  • repair publishing failure
  • correlate DB transaction dengan Kafka record
  • audit event creation

Jika metadata hanya dibuat saat publisher membaca outbox, event ID bisa berubah saat retry.

Itu buruk.

24. CDC/Debezium Metadata

Jika event berasal dari CDC/Debezium, metadata bisa berasal dari:

  • table name
  • database name
  • transaction ID
  • LSN/WAL position
  • operation type
  • source timestamp
  • Debezium connector metadata
  • outbox table columns

Jika memakai Debezium Outbox Event Router, outbox table biasanya menyediakan event metadata eksplisit.

Internal verification penting:

Apakah downstream consumer menerima raw CDC metadata, normalized event metadata, atau keduanya?

Raw CDC metadata berguna untuk debugging database changes.

Normalized event metadata berguna untuk business event contract.

Jangan campur tanpa dokumentasi.

25. Consumer Metadata Handling

Consumer harus memperlakukan metadata sebagai bagian dari processing contract.

Minimal consumer harus log:

  • topic
  • partition
  • offset
  • eventId
  • eventType
  • eventVersion
  • correlationId
  • causationId jika ada
  • aggregateId
  • tenantId jika ada
  • schema ID/version jika ada
  • consumer group
  • processing result

Contoh structured log:

{
  "message": "Processed Kafka event",
  "topic": "order.events.v1",
  "partition": 4,
  "offset": 912301,
  "consumerGroup": "billing-projection",
  "eventId": "evt-123",
  "eventType": "OrderSubmitted",
  "correlationId": "corr-abc",
  "aggregateId": "ORD-123",
  "result": "success",
  "durationMs": 42
}

Log tanpa event ID hampir tidak berguna saat incident.

26. DLQ Metadata

Event yang masuk DLQ harus mempertahankan metadata asli.

DLQ event sebaiknya menambahkan metadata failure:

{
  "original": {
    "topic": "order.events.v1",
    "partition": 4,
    "offset": 912301,
    "eventId": "evt-123",
    "eventType": "OrderSubmitted",
    "correlationId": "corr-abc"
  },
  "failure": {
    "consumerGroup": "billing-projection",
    "errorClass": "DeserializationException",
    "errorMessage": "Unknown enum value",
    "failedAt": "2026-07-11T03:10:00Z",
    "retryCount": 3
  },
  "payload": {}
}

DLQ tanpa original topic/partition/offset/eventId sulit direplay dengan aman.

DLQ tanpa error metadata sulit ditriage.

27. Auditability

Auditability berarti sistem bisa menjawab:

  • apa yang terjadi
  • kapan terjadi
  • siapa/apa yang memicu
  • service mana yang menghasilkan
  • event mana yang dikonsumsi
  • state apa yang berubah
  • apakah event direplay
  • apakah event duplicate
  • apakah event gagal dan masuk DLQ

Metadata audit harus stabil.

Jangan bergantung pada log text bebas.

Gunakan structured fields.

Untuk sistem CPQ/order management, auditability sangat penting karena event bisa memengaruhi quote approval, order state, fulfillment, fallout, billing, dan customer-visible status.

28. Metadata dan Ordering

Metadata membantu mendeteksi ordering issue.

Contoh field:

  • aggregateId
  • eventTime
  • sequenceNumber jika domain menyediakan
  • previousEventId jika digunakan
  • partitionKey
  • topic/partition/offset

Kafka hanya menjamin order dalam partition.

Jika event untuk order yang sama tidak memakai key yang sama, metadata akan membantu menemukan akar masalah.

Contoh detection:

OrderValidated aggregateId=ORD-123 partition=2 offset=500
OrderSubmitted aggregateId=ORD-123 partition=7 offset=900

Jika ordering per order diharapkan, ini salah desain key.

29. Metadata dan Idempotency

Consumer idempotency biasanya membutuhkan event ID.

Contoh inbox table:

CREATE TABLE processed_event (
    consumer_name TEXT NOT NULL,
    event_id TEXT NOT NULL,
    processed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    result TEXT NOT NULL,
    PRIMARY KEY (consumer_name, event_id)
);

Jika event ID tidak stabil, inbox pattern tidak efektif.

Jika event ID hilang saat replay, replay bisa dianggap event baru.

Jika event ID sama untuk dua business event berbeda, consumer bisa skip event valid.

Event ID generation harus direview serius.

30. Metadata dan Reconciliation

Reconciliation membutuhkan metadata untuk mencocokkan state antar sistem.

Contoh:

Order table says status=SUBMITTED.
Projection table says status=PENDING.
Find OrderSubmitted event by aggregateId=ORD-123.
Find consumer processing by eventId.
Find DLQ by eventId.
Find trace by correlationId.

Tanpa metadata, reconciliation berubah menjadi manual data archaeology.

Metadata juga membantu membedakan:

  • event belum dipublish
  • event sudah dipublish tapi belum dikonsumsi
  • event dikonsumsi tapi gagal
  • event dikonsumsi sukses tapi projection salah
  • event direplay dan menghasilkan duplicate

31. Metadata di Logs, Metrics, dan Traces

Metadata harus muncul di tiga observability surface:

Logs

Untuk diagnosis detail.

Wajib structured.

Metrics

Untuk aggregate signal.

Contoh label hati-hati:

  • eventType
  • consumerGroup
  • result
  • errorClass

Jangan jadikan eventId sebagai metric label karena high cardinality.

Traces

Untuk causal flow.

Trace span dapat menyimpan attribute:

  • messaging.system = kafka
  • messaging.destination.name
  • messaging.kafka.partition
  • messaging.kafka.offset
  • event.type
  • event.id
  • correlation.id

Perhatikan high cardinality policy di tracing backend.

32. Failure Mode

Failure mode metadata:

FailureDampak
eventId hilangidempotency sulit
eventId berubah saat retryduplicate tidak terdeteksi
correlationId dibuat ulangtrace lintas service putus
causationId tidak adaevent loop sulit dianalisis
tenantId salahcross-tenant risk
actorId berisi PIIprivacy exposure
eventTime memakai local timezonetemporal bug
schemaVersion tidak terlihatschema incident sulit ditriage
partitionKey tidak konsistenordering rusak
DLQ tidak preserve metadatareplay tidak aman
header hilang saat connectortraceability putus

33. Deteksi Metadata Failure

Tanda metadata buruk:

  • log tidak bisa difilter by eventId/correlationId
  • DLQ item tidak bisa dikaitkan ke original offset
  • consumer duplicate tidak bisa dideteksi
  • replay menghasilkan event yang terlihat baru
  • support tidak bisa menemukan request asal
  • tracing berhenti di producer dan tidak lanjut ke consumer
  • tenant-specific incident tidak bisa di-scope
  • ordering issue tidak bisa dibuktikan
  • event catalog dan payload nyata berbeda

Monitoring/validation yang membantu:

  • metadata completeness check di producer
  • schema/header validation di CI
  • runtime warning jika required metadata kosong
  • DLQ by missing metadata reason
  • log sampling untuk metadata completeness
  • dashboard event version/schema version distribution

34. Debugging dengan Metadata

Saat incident, gunakan metadata sebagai path diagnosis.

Contoh: consumer billing lag dan DLQ naik.

Langkah:

  1. Ambil sample DLQ.
  2. Catat original topic/partition/offset.
  3. Catat eventId, eventType, schemaVersion, correlationId, aggregateId.
  4. Cari producer log by eventId/correlationId.
  5. Cari outbox row by eventId.
  6. Cari HTTP request log by correlationId.
  7. Cari consumer log by eventId.
  8. Bandingkan schema version dengan deployment timeline.
  9. Tentukan apakah ini metadata issue, schema issue, data issue, atau business logic issue.

Metadata yang baik membuat langkah ini cepat.

Metadata yang buruk membuat langkah ini spekulatif.

35. Trade-Off Metadata

PilihanKelebihanRisiko
Metadata lengkapdebugging kuatpayload/header lebih besar
Metadata minimalsederhanaincident analysis sulit
Header-only metadatabersih dari payloadbisa hilang di connector/tooling
Envelope metadataself-containedsemua schema harus mengikuti envelope
Global standardkonsistenbutuh governance
Per-service standardfleksibelquery lintas service kacau
Correlation ID onlymudahcausality detail hilang
Full causation chainforensics kuatimplementasi lebih disiplin

Senior engineer harus menolak dua ekstrem:

Tidak ada metadata sama sekali.

Dan:

Semua informasi dimasukkan ke metadata tanpa alasan.

Metadata harus cukup untuk correctness, observability, auditability, dan operations.

36. Correctness Concern

Metadata memengaruhi correctness karena:

  • eventId menentukan deduplication
  • partitionKey menentukan ordering
  • tenantId menentukan isolation
  • eventTime menentukan temporal business logic
  • causationId menentukan saga transition
  • schemaVersion menentukan deserialization path
  • idempotencyKey menentukan duplicate command handling

Jika metadata salah, payload benar pun bisa diproses salah.

Contoh:

Payload orderId benar.
Partition key salah.
Consumer yang mengandalkan ordering per order memproses state out-of-order.

37. Performance Concern

Metadata menambah ukuran record.

Namun biasanya overhead metadata kecil dibanding manfaat debugging.

Yang perlu diwaspadai:

  • metadata terlalu besar
  • header berisi payload fragment
  • trace baggage berlebihan
  • actor/user detail verbose
  • high-cardinality metadata dipakai sebagai metric label
  • logging full metadata + payload untuk semua event high-volume

Prinsip:

Metadata lengkap, tetapi log/metric usage harus cardinality-aware.

38. Security and Privacy Concern

Metadata sering dianggap aman karena “bukan payload”.

Ini salah.

Metadata bisa mengandung sensitive data:

  • tenant ID
  • user ID
  • email
  • IP address
  • auth subject
  • organization ID
  • partner ID
  • correlation ID yang bisa dipakai tracking

Checklist:

  • Jangan taruh email/nama/phone di header jika ID cukup.
  • Jangan taruh token/JWT/secret di metadata.
  • Jangan log full auth claim.
  • Jangan expose sensitive metadata di DLQ viewer tanpa access control.
  • Pastikan retention metadata mengikuti policy data.

39. Observability Concern

Metadata harus masuk observability secara sengaja.

Recommended log fields:

event.id
event.type
event.version
correlation.id
causation.id
aggregate.id
tenant.id
source.service
messaging.topic
messaging.partition
messaging.offset
consumer.group
schema.id
processing.result

Metric labels harus lebih terbatas:

event.type
consumer.group
result
error.class

Jangan pakai:

event.id as metric label
correlation.id as metric label
aggregate.id as metric label

Itu akan menciptakan high-cardinality problem.

40. PR Review Checklist

Required metadata

  • Apakah eventId ada dan stabil?
  • Apakah eventType jelas?
  • Apakah eventVersion jelas?
  • Apakah eventTime UTC dan jelas semantics-nya?
  • Apakah sourceService ada?
  • Apakah aggregateId ada untuk domain event?
  • Apakah partitionKey sesuai aggregate/order requirement?

Traceability

  • Apakah correlationId dipropagasikan dari HTTP/request/workflow?
  • Apakah causationId diset dari command/event sebelumnya?
  • Apakah trace context diteruskan ke Kafka dan consumer?
  • Apakah logs consumer mencetak metadata penting?

Idempotency

  • Apakah eventId dipakai untuk inbox/dedup?
  • Apakah idempotencyKey berbeda jelas dari eventId?
  • Apakah retry publish mempertahankan eventId?
  • Apakah replay mempertahankan original eventId atau mencatat replay metadata?

Multi-tenancy and actor

  • Apakah tenantId berasal dari trusted context?
  • Apakah actorId/actorType cukup untuk audit tanpa mengekspos PII?
  • Apakah service account dibedakan dari user actor?

Headers vs payload

  • Apakah metadata location konsisten dengan standard internal?
  • Apakah connector/bridge preserve header yang dibutuhkan?
  • Apakah DLQ mempertahankan metadata?

Observability

  • Apakah metadata masuk structured logs?
  • Apakah metric labels tidak high-cardinality?
  • Apakah trace span punya Kafka attributes?
  • Apakah dashboard bisa filter by eventType/schemaVersion/consumerGroup?

41. Internal Verification Checklist

Untuk konteks CSG/team, verifikasi:

  • Apakah ada standard event metadata internal?
  • Apakah metadata disimpan di Kafka headers, payload envelope, atau hybrid?
  • Apakah JAX-RS filter membuat/meneruskan correlation ID?
  • Apakah trace context dipropagasikan ke Kafka producer/consumer?
  • Apakah eventId dibuat di service layer, outbox insert, atau publisher?
  • Apakah eventId stabil saat retry publish?
  • Apakah outbox table menyimpan metadata lengkap?
  • Apakah Debezium/CDC pipeline preserve metadata?
  • Apakah DLQ schema mempertahankan original metadata?
  • Apakah consumer logs mencetak eventId/topic/partition/offset/correlationId?
  • Apakah metrics memakai label yang aman dari high cardinality?
  • Apakah tenantId/actorId policy sudah sesuai privacy/security?
  • Apakah event metadata masuk event catalog/AsyncAPI?
  • Apakah replay tooling mempertahankan metadata atau mencatat replay metadata?
  • Apakah ada incident lama yang sulit ditelusuri karena metadata kurang?
  • Apakah platform/SRE punya dashboard correlation dari Kafka ke service logs?

42. Senior Engineer Heuristics

Gunakan heuristik berikut:

Jika event tidak punya eventId, consumer idempotency akan rapuh.
Jika event tidak punya correlationId, incident lintas service akan mahal.
Jika event tidak punya causationId, saga dan event loop sulit dianalisis.
Jika tenantId salah, itu bukan bug observability; itu security risk.
Jika partitionKey tidak bisa dijelaskan, ordering guarantee tidak bisa dipercaya.
Jika metadata hilang di DLQ, replay tidak production-safe.
Jika metadata tidak muncul di logs, metadata itu hampir tidak berguna saat incident.

43. Ringkasan

Event metadata adalah fondasi traceability event-driven system.

Payload menjelaskan fakta bisnis.

Metadata menjelaskan identitas, asal, sebab, versi, konteks, waktu, routing, idempotency, tenancy, actor, dan observability event.

Metadata yang baik membuat sistem Kafka:

  • bisa di-debug
  • bisa diaudit
  • bisa di-replay
  • bisa di-deduplicate
  • bisa dikorelasikan dengan HTTP request
  • bisa dikaitkan dengan outbox row
  • bisa diamati dari producer sampai consumer
  • bisa dianalisis saat DLQ, lag, missing event, duplicate event, dan ordering issue

Tanpa metadata standard, event-driven architecture akan terlihat decoupled saat design review, tetapi menjadi opaque saat production incident.

Lesson Recap

You just completed lesson 14 in build core. 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.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.