series = a field guide to the Phoenix tracing data model

Spans all the way down

Phoenix ingests OpenTelemetry traces and shows you sessions, turns, traces, and spans. Exactly one of those four things actually exists. This series is about what that fact buys us, what it costs us, and how the interface should be honest about it.

Here is the entire data model of OpenTelemetry tracing, and therefore the entire data model that arrives at Phoenix over the wire: a span is a named, timed operation with a bag of key–value attributes and three identifiers — its own span_id, an optional parent_id, and a trace_id shared with other spans. That's it. There is no trace record on the wire. There is no session record anywhere. There is certainly no "turn."

Everything above the span is a query. A trace is GROUP BY trace_id. A tree is a recursive join on parent_id. A session is GROUP BY an attribute (session.id) that the application promised to stamp on its spans. A turn is a styling decision applied to a trace's root span. None of this is a complaint — deriving structure from flat, immutable records is a fine architecture, and Part 2 argues it's mostly the right one. But an interface designed as if traces and sessions were sturdy first-class objects will keep tripping over the places where they aren't, and ours does, in ways this series will point at specifically.

One dataset, four projections
agent tool llm retriever

The nine records above never change — only the query does. That's the mental model this series keeps returning to: the span is the only object; trace, waterfall, and session are projections. When a projection looks like a container, it's worth asking what happens at its edges: when the root span never arrives, when two spans disagree about session.id, when a trace is still growing while you look at it. Those edge cases are where Phoenix's interface currently wobbles, and they're all downstream of treating a projection like an object.

The series

a companion series

The Second Write Path

This series is about the facts Phoenix stores. Its companion is about the judgments written on top of them — the annotation model and its identity key, evaluators as stored server-side objects, the construction UI, and the open design questions around online evals, scopes, and read amplification. Start here if you've read the model; read that one if you're building the evaluation layer.

Audience note. This is written for people who are comfortable with databases, distributed systems, and reading a schema, but new to AI observability. It assumes no familiarity with OpenTelemetry, LangSmith, or Phoenix itself. Where a claim is about Phoenix's actual behavior rather than its documentation, it cites the code — file and line — so you can check.