Trace = one user turn (one request). Session = group of traces sharing a sessionId (full conversation). Filter by session for chat history, trace for one turn.
Imagine reading a play. Each line a character speaks is like a trace, one back and forth. The whole scene with all the lines together is the session. If you want to understand the plot, you read the scene. If you want to debug a specific awkward line, you focus on just that line. In a chat product, each user message and the assistant reply is one trace; the whole conversation of dozens of messages is one session. You tell Langfuse which session a turn belongs to by setting a sessionId, usually your own conversation_id from the database.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Langfuse exposes two grouping levels for organizing telemetry: traces and sessions. They look like the same primitive at first (both group spans, both have IDs, both appear in the UI) but they answer different questions. Confusing them, or forgetting to wire sessions correctly, breaks every conversation-level analytic in a multi-turn chat product.
This walkthrough explains what each level actually represents at the data-model level, how the sessionId wiring works in practice, what changes in your debugging workflow when you filter by one versus the other, and the operational patterns (propagation, granularity choice, agent-loop handling) that keep the abstraction useful as a product grows.
Mental model: trace is the request unit (one user turn through your backend). Session is the user-arc unit (a conversation, identified by a sessionId you control). Set sessionId to your own conversation_id and the two levels click into place.
The data model: trace and session as nesting levels
A trace contains spans
A Langfuse trace is one end to end backend request. Inside a trace are spans (and generations, which are LLM-specific spans). For a typical chat turn, the trace might contain:
- A retrieval span (vector DB query + reranker).
- An LLM generation span (prompt to Claude or GPT).
- A tool-call span (if the model invoked a tool).
- A post-processing span (formatting, redaction).
All of these nest under the one trace.
A session contains traces
A session is one level above. It is a grouping of traces that share a sessionId attribute. Sessions are not a separate data type with their own spans; they are a view over traces.
The sessionId is yours to choose
Langfuse does not generate sessionIds for you. You set them in the SDK call when you create a trace. The recommended pattern for chat products is sessionId = your_conversation_id. That ties Langfuse sessions directly to rows in your application database, so 'user reported a bad conversation, id abc-123' becomes 'open Langfuse session abc-123' in one step.
Relationship to userId
UserId is a separate attribute. One user has many conversations, so one userId maps to many sessionIds. Set both: userId for user-level analytics ('top users by cost'), sessionId for conversation-level analytics ('top conversations by length').
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- Langfuse 3.x exposes sessions as a first-class view; the docs recommend `sessionId = conversation_id` for chat products.
- Chat-first products like Perplexity, Notion AI, and Claude.ai map conversation rows in their DB to Langfuse sessionIds 1-to-1.
What an interviewer would ask next. Try answering before peeking at the approach.
QHow would you compute per-conversation judge score in Langfuse?
Attach judge scores to each per-turn trace as usual; Langfuse aggregates them at the session level. The session view shows mean/median judge score across turns; you can also query the API for arbitrary aggregations.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Forgetting to set sessionId on each turn. Without it, every turn is an island and the conversation never groups.
60 second bullets to scan on the way to the call.
What a trace is (one user turn / one request)
What a session is (group of traces sharing sessionId)
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.