Distributed tracing is genuinely essential for the teams that need it and an expensive distraction for the teams that don't — and most Laravel teams don't, at least not yet. So it's worth understanding what it does, and being honest about whether your architecture is actually the shape that benefits from it before you spend a sprint wiring it up.
What it actually is
A request lands on Service A. Service A calls Service B. Service B calls Service C. Each service does work and sends back a response. You want to answer: "why was the user's request slow?" Distributed tracing lets you see every hop with its duration on one timeline.
The mechanism: a traceparent header propagates through every outbound call. Each service emits spans linked to the same trace ID. A trace backend (Jaeger, Tempo, Honeycomb, etc.) assembles the spans into a waterfall.
The W3C trace context
Example traceparent header
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
│ │ │ │
│ │ │ └─ flags (sampled)
│ │ └─ parent span id
│ └─ trace id (16 bytes, hex)
└─ version
Every service extracts the trace ID, creates a new span as a child of the parent span, and propagates a new traceparent (with its own span as the new parent) to downstream services.
When a Laravel monolith doesn't need it
If your architecture is:
- A single Laravel app
- A database (or a few)
- A couple of external HTTP integrations
- Some queued jobs running in the same codebase
...then per-request tracing within one app is all you need. Both Laravel Nightwatch Cloud and NightOwl record per-request data (DB queries, cache, queued jobs, outgoing HTTP, mail, notifications, exceptions) and let you drill into a single trace. Adding OpenTelemetry doesn't buy you more context — the bottleneck is always inside your one app or one of its direct dependencies.
When you do need it
- User request fans out across Laravel + a Node frontend SSR + a Python ML service + a Go worker
- Multiple teams own separate services that collaborate on user journeys
- You're seeing "it's slow" without being able to tell which service is slow
- You're building a platform where your Laravel app is called by many internal consumers
Setting it up in Laravel
Two credible paths:
- OpenTelemetry PHP SDK — install
open-telemetry/sdkandopen-telemetry/exporter-otlp. Instrument manually or use the auto-instrumentation packages. Ship to an OTel Collector, forward to Tempo/Jaeger/SigNoz/SaaS. See our OpenTelemetry in Laravel guide. - Vendor SDK — Sentry, New Relic, Datadog all ship SDKs that include trace propagation. Less portable but less work.
A cheaper middle path
There's a step between "nothing" and "full OpenTelemetry across every service": propagate a correlation ID. If each service simply logs a shared request ID passed in a header, you can't render a waterfall, but you can pull every service's logs for one request and read the timeline by hand. For a lot of teams that's most of the value of distributed tracing for a fraction of the effort, and it's the right thing to do first. Reach for real tracing when the by-hand version stops scaling. (See correlation IDs for the how.)