Langfuse just got faster →

Explore Observations in Langfuse Cloud Fast Preview (v4)

How to think about the new model

In v4, every operation your application performs — LLM calls, tool executions, retrievals, agent steps — is a first-class row in a single observations (spans) table. Think of it like a spreadsheet where each row is one operation, and you can slice by any column. The trace is just one column (trace_id) that groups related operations together, the same way session_id or user_id groups things.

This is more powerful than the old two-table model: instead of opening a trace and then scanning its children to find what went wrong, you can directly query across all operations. Find every GPT-4 call over $0.10, every retrieval that took more than 2 seconds, or every tool call that errored — without knowing which trace they belong to.

You will notice more rows in the table than before — that's expected. Each row is now one operation, not one trace. The key is to use filters and saved views to focus on what matters. Most users start with "root spans only" or "generations only" and go from there. The filter sidebar shows available values with counts, so you can discover which models, span names, or error levels are most common before committing to a filter.

For conceptual background, see the observation-centric data model. For broader release context, see the Fast Preview (v4) docs.

Common views (recipes)

These are some of the most useful starting points. Each can be saved as a saved view for one-click access.

I want to see…How to filter
All traces (like the old table)Filter for root spans (observations with no parent), save as a view
All LLM generationsFilter type = generation
Expensive LLM callsFilter type = generation, sort by total_cost descending
Errors for a specific userFilter by user_id and level = ERROR
Slow spans in a sessionFilter by session_id, sort by latency descending
All operations for one traceFilter by trace_id
Model performance comparisonFilter type = generation, group by model in a dashboard or sort by model column

We recommend setting up 2-3 saved views for your most common debugging workflows so the observations table feels immediately useful to your team.

Before → After

I want to have…v3v4
One row per traceTraces tableFilter for root spans (observations with no parent), save as a saved view
One row per trace, scoped to a user or sessionTraces table → filter by user/sessionSame as above, add user_id or session_id filter
Cost, latency, or errors by user, session, or span nameTraces table with filtersSelf-serve dashboards

Upgrade checklist

Ingest with a v4-compatible setup

Use one of these ingestion paths so your data appears in the unified table in real time:

  • Python SDK v4: migration guide
  • JS/TS SDK v5: migration guide
  • Direct OpenTelemetry ingestion: set x-langfuse-ingestion-version: 4 on your OTEL span exporter. If you use OTLP HTTP environment variables, add x-langfuse-ingestion-version=4 to OTEL_EXPORTER_OTLP_HEADERS. See OpenTelemetry setup.

If you are still sending data via older SDK versions, or via direct OpenTelemetry ingestion without x-langfuse-ingestion-version: 4, traces can appear in the unified tracing table with a delay of up to 10 minutes.

Propagate correlating attributes across spans

Use the SDK propagation helpers to propagate correlating attributes across child observations:

  • Python: propagate_attributes()
  • JS/TS: propagateAttributes()

This is very important for filters to work accurately. Attributes such as userId, sessionId, tags, metadata, version, and traceName should be available on observations so you can filter one table by request-level context and still work at observation granularity.

See Add attributes to observations for the SDK implementation details.

Share feedback

We are still iterating on the unified tracing experience. If something feels confusing, missing, or slower than expected, share feedback via support.

FAQ

Why are observations delayed or missing in the unified table?

The most common reason is that data is still being sent via older SDK versions or through a direct OpenTelemetry exporter without x-langfuse-ingestion-version: 4. In the new v4 experience, those setups can lead to multi-minute delays before traces show up in the unified table. If this happens, upgrade to Python SDK v4 or JS/TS SDK v5, or add the ingestion version header to your OTEL exporter.

How can I make this look more like the old traces table?

Create a saved view that filters to the root observation representing the start of each trace in your application (observations with no parent). That gives you a stable, trace-like list while still letting you drill into lower-level observations when needed. We recommend naming this view "Traces" so it feels familiar to your team.

The table shows too many rows — how do I make sense of it?

This is the most common reaction when first switching to the observations table. The old traces table showed one row per request; the new table shows every operation. The solution is filters and saved views — not scrolling. Start by filtering for root spans to get the trace-like view, then gradually explore more specific views (e.g., "all generations," "errors only"). Once you save 2-3 views that match your debugging workflows, the table will feel more focused than the old traces table, not less.

Can I get the old experience back?

Yes. For now, you can switch the v4 beta experience off in the UI and return to the previous tracing experience. This is temporary, though: the unified table will become the standard experience, so it is worth setting up saved views and instrumentation for the new model.


Was this page helpful?