Series MapLesson 09 / 62
Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Start HereOrdered learning track

Correlation, Causation, and Request Identity

Correlation ID, Causation ID, Request ID, Trace ID, and Business Keys

Standar identitas teknis dan bisnis untuk korelasi HTTP, messaging, workflow, background job, audit, dan production debugging.

18 min read3405 words
PrevNext
Lesson 0962 lesson track01–12 Start Here
#observability#logging#correlation-id#causation-id+12 more

Part 009 — Correlation ID, Causation ID, and Request ID

1. Core Idea

Production debugging becomes difficult when every service can only explain its own local execution. A customer-facing request in an enterprise system rarely stays inside one process. It enters through an edge layer, reaches a Java/JAX-RS endpoint, calls service logic, reads or writes PostgreSQL, touches Redis, publishes Kafka/RabbitMQ messages, triggers workflow execution, invokes downstream services, and may later continue through background jobs or human approval steps.

Without a consistent identity model, all those signals become disconnected fragments.

Correlation identity exists to answer:

"Which logs, metrics, traces, events, audit records, messages, workflow instances, and database changes belong to the same real-world operation?"

This part focuses on the identity vocabulary behind observability:

  • request ID
  • correlation ID
  • causation ID
  • trace ID
  • span ID
  • business transaction ID
  • idempotency key
  • message ID
  • event ID
  • process instance ID
  • quote ID / order ID / customer-facing business key

These identifiers are related, but they are not interchangeable. A senior engineer must know which one answers which production question.


2. The Problem: Logs Without Identity Are Local Noise

Consider a customer reports:

"My quote was approved, but the order was not created."

You search logs and find:

INFO Quote approved
INFO Publishing order creation event
INFO Received order creation event
ERROR Failed to create order

This is not enough.

You still need to know:

  • Which quote?
  • Which order attempt?
  • Which HTTP request started the change?
  • Which user or system actor triggered it?
  • Which Kafka/RabbitMQ message carried it?
  • Which workflow/process instance handled it?
  • Was it a retry or the first attempt?
  • Did another service receive the same event?
  • Was the failure related to the same trace?
  • Was it caused by this request or by a later background reconciliation job?

A log line without identity only proves that something happened somewhere. A log line with correct identity becomes evidence.


3. Identifier Taxonomy

3.1 Request ID

A request ID identifies one inbound request handled by a service boundary.

Typical scope:

  • one HTTP request
  • one API gateway request
  • one JAX-RS resource invocation
  • one consumer handling attempt
  • one job execution attempt

Common usage:

  • find all logs emitted while processing one HTTP request
  • diagnose one failed API call
  • map edge access log to application log
  • compare request start/end/error logs

Example:

request.id = req_01JABCD8S4M7Q2Z6R0P8K2T3N9

A request ID is usually short-lived. It should not be treated as the identity of an entire business transaction.

3.2 Correlation ID

A correlation ID groups multiple technical operations that belong to the same broader workflow or transaction.

Typical scope:

  • one customer operation across multiple services
  • one quote submission flow
  • one order capture flow
  • one asynchronous continuation after an API call
  • one workflow/process chain

Common usage:

  • correlate logs across services
  • connect HTTP request to Kafka/RabbitMQ message
  • connect producer and consumer processing
  • connect background job continuation to original operation
  • reconstruct incident timeline

Example:

correlation.id = corr_01JABCDKX7KCY04M7Q6H2P3Y5Z

The correlation ID often survives longer than one request ID.

3.3 Causation ID

A causation ID identifies the immediate parent event or command that caused the current operation.

It answers:

"Why did this operation happen? What directly triggered it?"

Typical usage:

  • event-driven systems
  • async workflows
  • retry chains
  • command processing
  • saga/process orchestration
  • audit reconstruction

Example:

event.id = evt_quote_approved_123
causation.id = evt_quote_submitted_987

Correlation groups a whole flow. Causation describes parent-child triggering.

3.4 Trace ID

A trace ID is part of distributed tracing. It identifies one distributed trace.

Typical scope:

  • a single end-to-end execution path represented by spans
  • one sampled or recorded distributed trace
  • one HTTP request and its downstream calls
  • sometimes extended across messaging boundaries if propagation is implemented

Example:

trace.id = 4bf92f3577b34da6a3ce929d0e0e4736

Trace ID is excellent for execution graph debugging. It is not always enough for business lifecycle debugging because traces may be sampled, truncated, expired, or broken at async boundaries.

3.5 Span ID

A span ID identifies one operation inside a trace.

Typical examples:

  • inbound HTTP handler span
  • PostgreSQL query span
  • Redis command span
  • Kafka produce span
  • Kafka consume span
  • RabbitMQ publish/consume span
  • downstream HTTP call span

Example:

span.id = 00f067aa0ba902b7

Span ID is useful when you need to connect a log line to an exact span, especially for high-detail trace/log correlation.

3.6 Business Transaction ID

A business transaction ID identifies a domain-level transaction or lifecycle.

Examples:

business.transaction.id = bt_quote_to_order_20260115_000019
quote.id = Q-2026-000123
order.id = O-2026-000771

This is the identity business users care about. It is often more durable than request ID or trace ID.

3.7 Idempotency Key

An idempotency key identifies a client or system operation that must be safely repeatable.

It answers:

"Have we already processed this operation?"

Common use cases:

  • create quote
  • submit order
  • accept payment-like command
  • publish command once
  • retry HTTP POST safely
  • deduplicate message processing

Example:

idempotency.key = idem_01JABCE2V2AHTQ9V0Y7M2Y8R8B

Idempotency key is not the same as request ID. A retry should usually have a different request ID but the same idempotency key.

3.8 Message ID

A message ID identifies one message instance in a broker or event system.

Examples:

message.id = msg_01JABCEYBM0X5ZG54KME4PHX47
kafka.topic = quote.events
kafka.partition = 4
kafka.offset = 982734
rabbitmq.delivery.tag = 98344

Message ID helps diagnose:

  • duplicate delivery
  • retry loops
  • DLQ movement
  • replay
  • poison message
  • consumer lag
  • redelivery

3.9 Event ID

An event ID identifies a domain event.

Example:

{
  "eventId": "evt_01JABCF9F4S3RQ59W35J8ZJ7T0",
  "eventType": "QuoteApproved",
  "quoteId": "Q-2026-000123"
}

Message ID and event ID may differ. A single event may be republished, retried, copied to DLQ, or replayed in a new message envelope.

3.10 Process Instance ID

A process instance ID identifies a workflow execution.

Common in Camunda or workflow orchestration:

process.instance.id = 9d7d2f6a-4d5f-4e20-a818-4c02a8e4d4a1
process.definition.key = quoteToOrder
business.key = Q-2026-000123

The process instance ID helps connect:

  • workflow incidents
  • failed jobs
  • human tasks
  • timers
  • message correlation
  • business lifecycle states

4. Identity Is Multi-Layered

A common mistake is trying to use one identifier for everything. That usually fails.

A healthy observability model uses layered identifiers:

LayerIdentifierPrimary Question
HTTP requestrequest.idWhat happened during this inbound request?
Distributed executiontrace.id, span.idWhat operations were executed and where was latency/error introduced?
Workflow/operationcorrelation.idWhich technical signals belong to the same broader operation?
Causal chaincausation.idWhat triggered this event/operation?
Domain lifecyclequote.id, order.id, business.transaction.idWhich business entity or lifecycle is affected?
Messagingmessage.id, event.id, topic/partition/offsetWhich async message or domain event is involved?
Idempotencyidempotency.keyIs this retry/duplicate safe?
Workflow engineprocess.instance.id, business.keyWhich process execution is affected?
Auditaudit.event.id, actor, action, targetWho did what, when, where, and why?

The goal is not to log every possible identifier everywhere. The goal is to ensure the right identifiers are available at the right boundary.


5. Request ID vs Correlation ID

Request ID

A request ID is usually generated per inbound request.

Example flow:

Client request A
  -> API Gateway assigns request.id=req-001
  -> Service A logs request.id=req-001
  -> Service A calls Service B with request.id=req-001 or downstream-request-id=req-002 depending on convention

Request ID is ideal for request-scoped debugging.

Correlation ID

Correlation ID should survive across multiple requests or async steps.

Example flow:

POST /quotes/Q-123/submit
  request.id=req-001
  correlation.id=corr-quote-submit-777

Kafka QuoteSubmitted event
  message.id=msg-222
  event.id=evt-333
  correlation.id=corr-quote-submit-777
  causation.id=req-001 or evt-previous

Order service consumer
  request.id=req-consume-444
  correlation.id=corr-quote-submit-777

The consumer should not reuse the producer HTTP request ID as its own request ID. It should create its own local request/processing ID while preserving the correlation ID.


6. Correlation ID vs Trace ID

A trace ID is a tracing-specific execution identity. A correlation ID is a broader application/business correlation identity.

They may be the same in simple systems, but in enterprise systems it is often safer to keep them conceptually separate.

Why not rely only on trace ID?

Because:

  • traces can be sampled
  • traces may not be retained as long as logs/audit
  • async trace continuity can break
  • business operations may span hours or days
  • workflow/human approval steps do not fit neatly into one trace
  • not every system participates in distributed tracing
  • external partners may not propagate trace headers

Trace ID is excellent for execution-level debugging. Correlation ID is better for long-lived operation reconstruction.

Use both:

{
  "request.id": "req-001",
  "correlation.id": "corr-777",
  "trace.id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span.id": "00f067aa0ba902b7",
  "quote.id": "Q-2026-000123"
}

This gives you:

  • log search by correlation ID
  • trace navigation by trace ID
  • business lookup by quote/order ID
  • exact span correlation by span ID

7. Correlation ID vs Causation ID

Correlation ID groups related work. Causation ID explains immediate trigger.

Example event chain:

Command: SubmitQuote
  event.id = cmd-001
  correlation.id = corr-777
  causation.id = null

Event: QuoteSubmitted
  event.id = evt-002
  correlation.id = corr-777
  causation.id = cmd-001

Event: QuoteApproved
  event.id = evt-003
  correlation.id = corr-777
  causation.id = evt-002

Command: CreateOrder
  event.id = cmd-004
  correlation.id = corr-777
  causation.id = evt-003

Event: OrderCreated
  event.id = evt-005
  correlation.id = corr-777
  causation.id = cmd-004

All events share the same correlation ID. Each event has a different causation ID pointing to the immediate parent.

This is extremely useful when debugging:

  • duplicate event emission
  • unexpected workflow transition
  • retry chains
  • saga compensation
  • delayed messages
  • manual intervention
  • reconciliation jobs

8. Business Keys Are Not Just Nice-to-Have

For CPQ/order management systems, business keys are operationally critical.

Examples:

  • quote.id
  • quote.version
  • order.id
  • order.line.id
  • customer.id
  • account.id
  • tenant.id
  • product.catalog.id
  • process.instance.id
  • business.transaction.id

A trace tells you what code executed. A business key tells you which customer-facing entity was affected.

During incidents, engineers often start from business evidence:

  • customer gave quote number
  • support ticket references order ID
  • workflow incident references process instance ID
  • settlement/reconciliation report references external order number
  • audit team asks who approved a change

If logs and traces do not contain business keys, production debugging becomes slow and indirect.

Business key rule

A business key should be included when:

  • it is already known at that layer
  • it is safe to log
  • it has bounded cardinality impact for logs/traces
  • it helps support or incident debugging
  • it does not violate privacy/security policy

For metrics, business keys are dangerous as labels because they are high cardinality. For logs/traces, they are often acceptable if protected by access control and retention policy.


A practical baseline for structured logs:

{
  "timestamp": "2026-01-15T10:15:30.123Z",
  "level": "INFO",
  "service.name": "quote-service",
  "service.version": "1.42.0",
  "environment": "prod",
  "request.id": "req_01JABC...",
  "correlation.id": "corr_01JABC...",
  "trace.id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span.id": "00f067aa0ba902b7",
  "tenant.id": "tenant_abc",
  "actor.id": "user_123",
  "quote.id": "Q-2026-000123",
  "order.id": null,
  "event.id": null,
  "causation.id": null,
  "message": "Quote submission accepted"
}

For async consumer logs:

{
  "timestamp": "2026-01-15T10:15:34.550Z",
  "level": "INFO",
  "service.name": "order-service",
  "request.id": "req_consumer_01JABC...",
  "correlation.id": "corr_01JABC...",
  "trace.id": "9f3e...",
  "span.id": "a0b1...",
  "message.id": "msg_01JABC...",
  "event.id": "evt_quote_approved_01JABC...",
  "causation.id": "evt_quote_submitted_01JABC...",
  "kafka.topic": "quote.events",
  "kafka.partition": 4,
  "kafka.offset": 982734,
  "quote.id": "Q-2026-000123",
  "message": "Processing QuoteApproved event"
}

For workflow logs:

{
  "service.name": "workflow-service",
  "correlation.id": "corr_01JABC...",
  "process.instance.id": "9d7d2f6a-4d5f-4e20-a818-4c02a8e4d4a1",
  "process.definition.key": "quoteToOrder",
  "business.key": "Q-2026-000123",
  "activity.id": "approveQuoteTask",
  "quote.id": "Q-2026-000123",
  "message": "Workflow task completed"
}

10. Boundary Rules

10.1 Inbound HTTP Boundary

At HTTP ingress:

  • accept trusted correlation/request headers only from trusted upstreams
  • generate missing request ID
  • generate missing correlation ID
  • validate header length and allowed characters
  • prevent spoofing from public clients
  • attach context to MDC
  • attach context to trace/span attributes where appropriate
  • return request ID in response header if policy allows

Recommended inbound fields:

request.id
correlation.id
trace.id
span.id
http.method
http.route
http.status_code
tenant.id
actor.id
client.ip
user_agent.original

10.2 Outbound HTTP Boundary

For downstream calls:

  • propagate trace context using standard propagator
  • propagate correlation ID according to internal convention
  • optionally generate downstream request ID if convention requires
  • never propagate untrusted headers blindly
  • include correlation ID in logs around call start/end/error

Recommended outbound fields:

correlation.id
trace.id
span.id
peer.service
http.method
http.url or http.route depending on privacy policy
http.status_code
network.peer.name
error.type

10.3 Kafka/RabbitMQ Producer Boundary

When publishing:

  • include correlation ID in message headers
  • include causation ID from current command/event/request
  • include event ID in payload or envelope
  • include trace context if tracing supports messaging propagation
  • include business key if safe and useful
  • log publish attempt and publish result

Recommended message headers:

correlation-id
causation-id
traceparent
tracestate
message-id
event-id
producer-service
schema-version

Actual header names must follow internal standards. Do not invent incompatible names if a team standard already exists.

10.4 Kafka/RabbitMQ Consumer Boundary

When consuming:

  • extract correlation ID
  • extract trace context
  • create local processing/request ID
  • attach event ID and message ID
  • attach topic/queue metadata
  • attach business key if available
  • log start/end/failure of processing
  • preserve causation when publishing follow-up events

Important:

The consumer processing attempt should usually have its own local request ID. The correlation ID should be preserved.

10.5 Background Job Boundary

For scheduled jobs:

  • generate job execution ID
  • generate or derive correlation ID per job run
  • attach job name, schedule, shard, batch ID
  • attach reconciliation target if applicable
  • attach processed count, failed count, skipped count
  • attach business keys only in detailed logs, not metric labels

10.6 Workflow Boundary

For Camunda/workflow:

  • use process instance ID
  • use business key
  • preserve correlation ID when starting process
  • preserve event/causation ID when correlating messages
  • log activity/task transitions
  • audit business-significant transitions

11. JAX-RS Context Propagation Sketch

A simplified JAX-RS request filter can normalize identifiers.

package com.example.observability;

import jakarta.annotation.Priority;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.ext.Provider;
import org.slf4j.MDC;

import java.io.IOException;
import java.util.Optional;
import java.util.UUID;

@Provider
@Priority(Priorities.AUTHENTICATION)
public class CorrelationContextFilter implements ContainerRequestFilter, ContainerResponseFilter {

    public static final String REQUEST_ID_HEADER = "X-Request-ID";
    public static final String CORRELATION_ID_HEADER = "X-Correlation-ID";

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        String requestId = normalizeOrGenerate(requestContext.getHeaderString(REQUEST_ID_HEADER), "req");
        String correlationId = normalizeOrGenerate(requestContext.getHeaderString(CORRELATION_ID_HEADER), "corr");

        MDC.put("request.id", requestId);
        MDC.put("correlation.id", correlationId);

        requestContext.setProperty("request.id", requestId);
        requestContext.setProperty("correlation.id", correlationId);
    }

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
            throws IOException {
        String requestId = Optional.ofNullable((String) requestContext.getProperty("request.id"))
                .orElse(MDC.get("request.id"));
        String correlationId = Optional.ofNullable((String) requestContext.getProperty("correlation.id"))
                .orElse(MDC.get("correlation.id"));

        if (requestId != null) {
            responseContext.getHeaders().putSingle(REQUEST_ID_HEADER, requestId);
        }
        if (correlationId != null) {
            responseContext.getHeaders().putSingle(CORRELATION_ID_HEADER, correlationId);
        }

        MDC.remove("request.id");
        MDC.remove("correlation.id");
    }

    private String normalizeOrGenerate(String raw, String prefix) {
        if (raw == null || raw.isBlank() || raw.length() > 128 || !raw.matches("[A-Za-z0-9._:-]+")) {
            return prefix + "_" + UUID.randomUUID();
        }
        return raw;
    }
}

This is intentionally simplified. Production systems should verify:

  • trusted header boundary
  • naming convention
  • UUID/ULID strategy
  • MDC cleanup on exception path
  • async request lifecycle
  • OpenTelemetry propagation integration
  • privacy/security header policy
  • response header policy

12. OpenTelemetry Relationship

OpenTelemetry already handles trace context propagation when configured correctly. However, application-level correlation may still be needed.

A common approach:

  • OTel manages trace.id and span.id
  • application filter manages request.id and correlation.id
  • structured logging includes both
  • selected business keys are attached as log fields and span attributes
  • message producers propagate both trace context and correlation context

Example span enrichment:

import io.opentelemetry.api.trace.Span;

public final class ObservabilityContext {
    public static void enrichCurrentSpan(String correlationId, String tenantId, String quoteId) {
        Span span = Span.current();
        span.setAttribute("correlation.id", correlationId);
        if (tenantId != null) {
            span.setAttribute("tenant.id", tenantId);
        }
        if (quoteId != null) {
            span.setAttribute("quote.id", quoteId);
        }
    }
}

Be careful with span attributes:

  • avoid high-cardinality attributes if the tracing backend indexes them aggressively
  • do not attach secrets or raw tokens
  • avoid full SQL parameters
  • avoid large payloads
  • verify internal semantic conventions

13. Messaging Envelope Pattern

A robust event envelope separates business payload from observability metadata.

{
  "metadata": {
    "eventId": "evt_01JABCF9F4S3RQ59W35J8ZJ7T0",
    "eventType": "QuoteApproved",
    "eventVersion": "1.0",
    "correlationId": "corr_01JABC...",
    "causationId": "evt_quote_submitted_01JABC...",
    "idempotencyKey": "idem_01JABC...",
    "producerService": "quote-service",
    "producedAt": "2026-01-15T10:15:31.000Z",
    "tenantId": "tenant_abc",
    "businessKey": "Q-2026-000123"
  },
  "payload": {
    "quoteId": "Q-2026-000123",
    "approvedBy": "user_123",
    "approvedAt": "2026-01-15T10:15:30.900Z"
  }
}

For Kafka/RabbitMQ, some metadata may live in headers instead of payload. The exact design should be consistent with schema governance, broker conventions, tracing propagation, and security policy.


14. Metric Label Warning

Identifiers are useful in logs and traces. They are dangerous in metric labels.

Avoid metric labels such as:

request_id
correlation_id
trace_id
span_id
message_id
event_id
quote_id
order_id
user_id
raw_path
error_message

These create high cardinality and may damage metric backend performance or cost.

Prefer bounded labels:

service
endpoint_template
http_method
status_code_class
dependency
operation_type
outcome
error_type
queue_name
topic
consumer_group
tenant_tier   # if bounded and approved

Business IDs belong in logs, traces, audit events, or searchable event stores, not high-cardinality time-series labels.


15. Audit Relationship

Audit logs need identity too, but audit identity is not the same as request correlation.

A good audit event may include:

{
  "audit.event.id": "aud_01JABC...",
  "timestamp": "2026-01-15T10:15:30.123Z",
  "actor.id": "user_123",
  "actor.type": "human",
  "action": "QUOTE_APPROVED",
  "target.type": "quote",
  "target.id": "Q-2026-000123",
  "correlation.id": "corr_01JABC...",
  "request.id": "req_01JABC...",
  "trace.id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "source.ip": "203.0.113.10",
  "reason": "approval workflow step completed"
}

Correlation fields help connect audit event to operational evidence. Audit event ID gives the compliance record its own identity.


16. Failure Modes

16.1 Missing Correlation ID

Symptoms:

  • logs cannot be connected across services
  • support ticket requires manual guesswork
  • async consumer logs cannot be tied to producer logs
  • incident timeline has gaps

Likely causes:

  • ingress does not generate correlation ID
  • downstream propagation missing
  • message headers not populated
  • background job starts without context
  • MDC cleared too early

16.2 Reused Request ID Across Async Boundaries

Symptoms:

  • multiple consumer attempts appear as one request
  • retry attempts are hard to distinguish
  • request duration becomes misleading

Fix:

  • preserve correlation ID
  • generate new local request/processing ID per attempt
  • include message ID and event ID

16.3 Trace Break

Symptoms:

  • trace stops at producer
  • consumer starts a new unrelated trace
  • logs have trace ID only in one service

Likely causes:

  • missing propagation headers
  • unsupported broker instrumentation
  • custom producer/consumer wrapper drops headers
  • async executor loses context

16.4 Context Spoofing

Symptoms:

  • external client controls internal correlation headers
  • malicious or accidental huge header value pollutes logs
  • log search results are polluted by forged IDs

Controls:

  • only trust headers from known gateways
  • validate length/characters
  • regenerate unsafe identifiers
  • preserve external request ID separately if needed

16.5 Business Key Missing

Symptoms:

  • logs show technical flow but cannot answer which quote/order was affected
  • support engineer cannot search by customer-facing reference
  • RCA cannot connect failure to business impact

Fix:

  • attach business key once known
  • include it in logs/traces/audit
  • avoid metric labels for high-cardinality business IDs

16.6 Cardinality Explosion

Symptoms:

  • metric backend becomes expensive or slow
  • dashboard queries time out
  • storage cost spikes

Likely causes:

  • request ID, trace ID, order ID, user ID used as metric labels
  • raw path instead of endpoint template
  • exception message used as label

17. Debugging Playbook

When investigating a failed quote/order operation:

  1. Start from the business key.

    • quote ID
    • order ID
    • customer/account ID if allowed
    • process instance ID
  2. Search logs by business key.

  3. Extract correlation ID.

  4. Search logs across services by correlation ID.

  5. Find request IDs for each local operation.

  6. Find trace IDs attached to request logs.

  7. Open distributed traces and inspect:

    • failed spans
    • slow spans
    • downstream calls
    • DB calls
    • message publish/consume spans
  8. For async processing, inspect:

    • event ID
    • message ID
    • Kafka topic/partition/offset
    • RabbitMQ exchange/queue/routing key
    • retry/DLQ movement
    • event age
  9. For workflow, inspect:

    • process instance ID
    • activity ID
    • failed jobs
    • incidents
    • timers
    • human task aging
  10. For audit, inspect:

    • actor
    • action
    • target
    • before/after
    • timestamp
    • request/correlation IDs

18. PR Review Checklist

When reviewing a PR that touches request handling, async messaging, workflow, or audit:

  • Does the code preserve correlation.id?
  • Does each local operation have a distinct request.id or processing ID?
  • Are trace.id and span.id available in logs?
  • Are business keys logged once they are known?
  • Are business keys avoided as metric labels?
  • Does event publishing include event.id and causation.id?
  • Does consumer processing extract and restore context?
  • Does retry/DLQ handling preserve original event identity?
  • Does workflow start/correlation include business key and correlation ID?
  • Does audit logging include actor, action, target, request ID, and correlation ID?
  • Are untrusted inbound headers validated?
  • Is context cleaned up after request/consumer/job completion?
  • Are sensitive IDs protected according to privacy policy?
  • Are context fields standardized with existing team conventions?

19. Internal Verification Checklist

Verify with the internal codebase, senior engineers, SRE/platform team, or security team:

Header and Field Standards

  • What is the official request ID header?
  • What is the official correlation ID header?
  • Are W3C traceparent and tracestate used?
  • Is baggage allowed?
  • Are custom headers allowed through ingress/API gateway?
  • Which headers are trusted from external clients?

Logging Context

  • Which fields are included in JSON logs?
  • Are request.id, correlation.id, trace.id, and span.id always present?
  • Are tenant.id, actor.id, quote.id, and order.id logged?
  • Is MDC cleanup implemented correctly?
  • Is executor/thread pool context propagation implemented?

Messaging

  • Are correlation and causation IDs included in Kafka/RabbitMQ headers or payload?
  • Is event.id mandatory?
  • Is message.id generated by producer, broker, or both?
  • Are retry and DLQ flows preserving identity?
  • Are event schemas versioned?

Workflow

  • Is Camunda/process business key aligned with quote/order ID?
  • Is process instance ID logged in application logs?
  • Are message correlation failures observable?
  • Are workflow incidents correlated to service logs?

Tracing

  • Is OpenTelemetry enabled?
  • Are logs correlated with trace/span IDs?
  • Does tracing continue across Kafka/RabbitMQ?
  • Are traces sampled?
  • Are critical business flows sampled differently?

Metrics and Cost

  • Are high-cardinality labels prohibited?
  • Are raw paths normalized to route templates?
  • Are business IDs excluded from metric labels?
  • Is there a cardinality dashboard/report?

Security and Privacy

  • Are actor/customer/tenant identifiers considered sensitive?
  • Are tokens/cookies/auth headers stripped?
  • Are IDs encrypted, hashed, masked, or raw?
  • Who can query logs containing business identifiers?
  • What is retention for operational logs vs audit logs?

20. Practical Mental Model

Use this rule:

Request ID tells you the local operation. Correlation ID tells you the wider story. Causation ID tells you why the next thing happened. Trace ID tells you the execution graph. Business key tells you who or what was affected.

A mature production system does not rely on one identifier. It carries a small, disciplined identity set across boundaries and uses each identifier for the question it is designed to answer.


21. Summary

In enterprise Java/JAX-RS observability, identity is not decorative metadata. It is the backbone of production evidence.

You should now be able to:

  • distinguish request ID, correlation ID, causation ID, trace ID, span ID, event ID, message ID, idempotency key, process instance ID, and business key
  • decide which identifier belongs in logs, traces, metrics, audit events, message headers, and workflow metadata
  • avoid confusing trace ID with long-lived business correlation
  • preserve correlation across HTTP, Kafka, RabbitMQ, background jobs, and workflow
  • avoid high-cardinality metric labels
  • review PRs for context propagation and production-debugging readiness
  • identify what must be verified internally instead of assuming a team standard

The next part applies these identity concepts directly to JAX-RS request/response logging.

Lesson Recap

You just completed lesson 09 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.

Continue The Track

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