Definition:
A Correlation ID is a unique identifier attached to a request that travels with it across every service it touches in a distributed system. Itβs the breadcrumb trail that lets you trace a single user action through dozens of microservices, message queues, and databases.
In one sentence: Tag a request at the door with a unique ID, then use that ID to follow it everywhere it goes.
Analogy β The Package Tracking Number Imagine you order a jacket online. The order triggers a chain of events:
π Order π¦ Warehouse π Shipping π Delivery System β System β Provider β Confirmation Without a tracking number With a tracking number βWhereβs my order??β β Shrug. Call every department. Enter tracking # β See exactly where it is Warehouse error? Nobody knows which order is affected. βOrder #TRK-8821 failed at warehouse β re-pick itβ Customer complains? 20-minute investigation across 5 systems. Search logs for TRK-8821 β instant full timeline A Correlation ID is that tracking number β for every single request inside your system.
How It Works
Client Service A Service B Service C
β β β β
β GET /order/42 β β β
β X-Correlation-ID: abc β β β
βββββββββββββββββββββββββββΆβ β β
β β POST /inventory β β
β β X-Correlation-ID: abc β
β βββββββββββββββββββββΆβ β
β β β PUBLISH order.paidβ
β β β correlationId=abc β
β β βββββββββββββββββββββΆβ
β β β β
β ββββ 200 OK ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β β β
βΌ βΌ βΌ βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Every log line, every message, every DB row stamped with: "abc" β
β Search "abc" β full timeline instantly β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Example:
End-to-End in a Microservice System
1οΈβ£ Frontend / Gateway β Create or Forward the ID
# API Gateway (or first service that handles the request)
from flask import Flask, request
import uuid
import requests
app = Flask(__name__)
@app.before_request
def attach_correlation_id():
# If the caller already sent one, use it. Otherwise, create it.
correlation_id = request.headers.get('X-Correlation-ID')
if not correlation_id:
correlation_id = str(uuid.uuid4())
# Store it so every downstream call can access it
request.correlation_id = correlation_id
print(f"π [{correlation_id}] Request started: {request.method} {request.path}")
@app.route('/order', methods=['POST'])
def create_order():
order_data = request.json
cid = request.correlation_id
print(f"π¦ [{cid}] Creating order for: {order_data['item']}")
# Call service B β PASS THE CORRELATION ID
resp = requests.post(
"http://inventory-service/check",
json={"item_id": order_data["item"]},
headers={"X-Correlation-ID": cid} # β THE KEY LINE
)
print(f"π [{cid}] Inventory responded: {resp.status_code}")
return {"status": "ok", "correlation_id": cid}
2οΈβ£ Middle Service β Receive It, Log It, Forward It
# Inventory Service
from flask import Flask, request
app = Flask(__name__)
@app.route('/check', methods=['POST'])
def check_inventory():
cid = request.headers.get('X-Correlation-ID', 'no-cid')
print(f"π [{cid}] Checking inventory for item_id={request.json['item_id']}")
print(f"π [{cid}] Stock found: 23 units")
# Simulate a database insert with correlation ID
# INSERT INTO inventory_logs (item_id, action, correlation_id) VALUES (42, 'checked', 'abc')
return {"available": True}
3οΈβ£ Logging β The Real Payoff
import logging
import sys
# Structured logging that always includes the correlation ID
formatter = logging.Formatter(
'{"time": "%(asctime)s", "level": "%(levelname)s", "cid": "%(cid)s", "msg": "%(message)s"}'
)
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter)
logger = logging.getLogger("service")
logger.addHandler(handler)
# Usage in any service
def log(cid, message, level="info"):
extra = {"cid": cid}
getattr(logger, level)(message, extra=extra)
log("abc-123", "Order created") # {"cid": "abc-123", "msg": "Order created"}
log("abc-123", "Payment processed") # {"cid": "abc-123", "msg": "Payment processed"}
log("abc-123", "Shipment dispatched") # {"cid": "abc-123", "msg": "Shipment dispatched"}
4οΈβ£ Searching β The Magic Moment
Now in your log aggregator (ELK, Splunk, Datadog, Grafana Loki):
# Find EVERYTHING related to a single user request
$ grep "abc-123" /var/log/*.json
[12:03:01] abc-123 β Gateway: Request started POST /order
[12:03:01] abc-123 β Orders: Creating order for "jacket"
[12:03:02] abc-123 β Inventory: Checking stock for item #42
[12:03:02] abc-123 β Inventory: Stock: 23 units
[12:03:03] abc-123 β Payment: Charging $89.99
[12:03:03] abc-123 β Payment: Payment approved
[12:03:04] abc-123 β Warehouse: Pick ticket created #WH-551
[12:03:04] abc-123 β Orders: Order complete β 200 OK
One search. The full story. Every service. In order.