Why is one order slow? A real case of locating a transaction latency bottleneck with distributed tracing, including instrumentation rules, a sampling strategy for financial workloads and P99 alerting advice that found the root cause in under 30 minutes.
The classic question in financial systems: a user says "checkout is slow", but slow where? The gateway? Risk control? Accounts? Clearing? The database? Without tracing you guess layer by layer from logs, and a single chain crossing a dozen services costs half a day of manual work.
Distributed tracing turns one transaction into a chain of per-hop timings, so you see at a glance where the bottleneck sits — and, just as importantly, where it doesn't.
Finance demands more from observability than a typical web service:
Observe lets you attach business tags to spans (order_id, user_id, merchant_id), tying technical traces to business entities. This is what turns "some request was slow" into "order 884213 from merchant 7 stalled in risk control".
Before digging into any single transaction, check four signals per service: latency (P99), traffic (requests per second), errors (rate), and saturation (queue depth, connection-pool usage). Together they usually tell you which service to zoom into. In the case below, the first thing that looked wrong was a latency spike at 14:00 with a flat error rate — a pattern that pointed at a resource bottleneck rather than a code bug.
Once you've picked the service, tracing takes over. Sort spans by duration to find the long poles, then diff a slow trace against a normal one. The span that is dramatically longer in the slow trace is almost always where the time is going; everything downstream of it is usually just waiting on that one call.
A real trading team's incident (anonymized):
Symptom: "order success rate drops one point around 14:00 every day." Monitoring shows P99 latency at 14:00 jumping from 300ms to 4s, but only on certain channels.
How they found it:
success=false.From "something is wrong" to root cause took under 30 minutes, because every span's duration and error status was recorded in the trace. Without tracing, step 2 — knowing the stall was in risk control, not the gateway or the database — would have been a day of log archaeology.
order_id and user_id into span attributes, not just technical fields.success=false transactions and sample successful ones at 10%.