Langfuse v4: up to 165ร— faster ยท Read more
DocsExport to Blob Storage

Export to blob storage

Where is this feature available?
  • Hobby
    Not Available
  • Core
    Not Available
  • Pro
    Teams Add-on required
  • Enterprise
    Available
  • Self Hosted
    Available

Overview

Schedule exports to Amazon S3, S3-compatible storage, Google Cloud Storage, or Azure Blob Storage every 20 minutes, hourly, daily, or weekly.

Configure the export

Create the integration

  1. Open Project Settings > Integrations > Blob Storage.
  2. Select your provider and enter its bucket, path, and credentials. Self-hosters can find per-vendor bucket and credential setup on the blob storage deployment page.
  3. Choose the file format, schedule, export mode, and field groups.
  4. Enable the integration and save. The first run starts shortly afterward.

Blob storage integration setup

SettingChoices and behavior
Provider and accessAWS S3, S3 Compatible Storage, or Azure Blob Storage. Google Cloud Storage is reached through S3 Compatible Storage: set the endpoint to https://storage.googleapis.com and authenticate with an HMAC key pair rather than a service account.
FormatParquet (default), CSV, JSON, or JSONL. Text formats can be gzip-compressed; Parquet uses its own encoding and compression.
ScheduleEvery 20 minutes, hourly, daily, or weekly. Each run exports one time window.
Export ModeFull history starts at the project's earliest data; From setup date starts when the integration is enabled; From custom date starts at a selected date. Changing this setting resets the sync position and re-scans from that point.

The integration settings page shows a status badge:

BadgeMeaning
ActiveEnabled and synced; the next run is scheduled.
RunningA run is in progress.
QueuedA run is due and waiting.
PendingEnabled but has not run yet.
DisabledTurned off.
ErrorThe last run failed; the message and timestamp are shown.

Parquet notes

  • Observation files omit input_price, output_price, and total_price. Use cost_details and total_cost; trace and score fields are unaffected.
  • On self-hosted ClickHouse older than 25.11, upgrade ClickHouse or use CSV, JSON, or JSONL because incomplete Parquet output may not be reported.

Use Validate before saving to check that Langfuse can access the target with the supplied credentials. The integration then writes all output beneath the configured prefix without changing other objects in the bucket.

Langfuse writes exports to your bucket using this structure:

{prefix}{project-id}/
โ”œโ”€โ”€ observations_v2/
โ”‚   โ””โ”€โ”€ {timestamp}.{parquet|json|jsonl|csv}[.gz]
โ”œโ”€โ”€ scores/
โ”‚   โ””โ”€โ”€ {timestamp}.{parquet|json|jsonl|csv}[.gz]
โ””โ”€โ”€ manifests/
    โ””โ”€โ”€ {timestamp}.json

Field selection

Observation columns are configurable; score columns are fixed.

New integrations select all eleven field groups. core is required; disable other groups to reduce file size or omit sensitive data.

GroupFields
coreend_time, id, parent_observation_id, project_id, start_time, trace_id, type
basicbookmarked, environment, is_root_observation, level, name, public, session_id, status_message, user_id, version
timecompletion_start_time, created_at, updated_at
ioinput, output
metadatametadata
modelinput_price, model_id, model_parameters, output_price, provided_model_name, total_price
usagecost_details, total_cost, usage_details, usage_pricing_tier_id, usage_pricing_tier_name
promptprompt_id, prompt_name, prompt_version
metricslatency, time_to_first_token
trace_contextrelease, tags, trace_name
toolstool_call_names, tool_calls, tool_definitions

Changes apply only to future exports. See the observation field reference for types and descriptions.

Scores are always exported and their fields cannot be selected.

CategoryFields
Identityid, project_id, timestamp, created_at, updated_at
Context and linkstrace_id, observation_id, session_id, dataset_run_id, environment
Scorename, data_type, value, string_value, source, comment

See the score field reference for types and descriptions.

Configure through the API

Use the public endpoint to read or update the integration:

GET /api/public/integrations/blob-storage
PUT /api/public/integrations/blob-storage

On PUT, exportFieldGroups must include core; omit the property to keep the current selection. compressed applies only to CSV, JSON, and JSONL.

See the REST API reference for authentication, provider settings, and the complete schema.

Process exports

Use each run's manifest as the unit of work.

Know when an export is complete

A run is complete only when its manifest exists at {prefix}{project-id}/manifests/{timestamp}.json. Langfuse writes it after every data file uploads successfully.

If an upload fails, no manifest is written. The run is retried and any data objects under the same keys are overwritten.

When a manifest appears:

  1. Read files[].
  2. Fetch every full object key in files[].key. Do not derive filenames or list table directories.
  3. Deduplicate records by ID because adjacent export windows share an inclusive boundary.
FieldPurpose
windowInclusive minTimestamp and maxTimestamp for the run
exportSource, tablesExport source and tables included
files[]Object key, table, format, compression, uploaded size, and row count for each data file

For Parquet, files[].rowCount is null; inspect the file metadata when you need a count. Ignore unknown manifest fields so additive changes do not break your parser.

Trigger your pipeline

Subscribe to object-created events filtered to {prefix}{project-id}/manifests/, then fetch the manifest and process each files[].key.

If your S3-compatible provider has no object-created events, poll the manifest prefix and checkpoint the latest processed key. Manifest names sort by export timestamp.

Make manifest processing idempotent. Provider events can be delivered more than once, and a catch-up can create several manifests close together.

Upgrade a legacy export

Complete this upgrade if your integration uses Traces and observations (legacy) or your bucket receives traces/ and observations/ files. On Langfuse Cloud, remaining legacy exports switch on November 16, 2026 (2026-11-16). On self-hosted v4, the legacy source stops producing data after the server switches to events_only.

What changes in the exported data

The legacy source writes observation data to observations/ and trace context to a separate traces/ file, which consumers join on trace_id. The enriched source writes a single observations_v2/ file in which each observation row already carries its trace context.

Field groups select columns in both observation files. Three groups contain fewer fields in the legacy observations/ file; the rest are identical:

Groupobservations_v2/observations/
basicbookmarked, environment, is_root_observation, level, name, public, session_id, status_message, user_id, versionenvironment, level, name, status_message, version
usagecost_details, total_cost, usage_details, usage_pricing_tier_id, usage_pricing_tier_nameSame, without usage_pricing_tier_id
trace_contextrelease, tags, trace_nameNo effect; these fields are in the traces/ file (name for trace_name)

The traces/ file itself has a fixed schema that field groups do not apply to. Its trace-level input, output, metadata, timestamp, and version have no direct equivalent in observations_v2/, where identically named fields hold observation-level data.

For every column in each file, see the legacy field reference.

Switch to enriched observations

Most integrations can switch directly once their consumer supports the enriched layout:

On self-hosted Langfuse v4, first switch the server to dual write mode and complete the historic data migration.

Enriched export sources require the deployment to write the v4 events table, so they are unavailable only in legacy write mode. Legacy export sources are unavailable in events_only, which is the default. Switch the integration before the server's events_only cutover.

  1. Prepare the new consumer. Process observations_v2/ and scores/ from each manifest's files[].key. Use the enriched field reference.
  2. Switch the export. Select Enriched observations (recommended).
  3. Verify and retire legacy. Process the next completed export with the new consumer. After it succeeds, retire the consumer that reads traces/ and observations/.

Optional: keep both layouts during the cutover.

If your pipeline cannot tolerate a cutover gap, temporarily select Traces and observations (legacy) and enriched observations after step 1.

This writes observations/ and observations_v2/ for subsequent windows only; it does not backfill earlier exports. Run both consumers until the new one is validated, then continue with step 2.

Do not load both observation layouts into the same production dataset. Check the export compatibility matrix if this option is unavailable.

Cutover checks

  • All deployments: traces/ and observations/ stop receiving files after the switch, including empty files. Use manifests/ as the run-completion signal.
  • Langfuse Cloud: Ignore DEPRECATION_NOTICE.txt when processing exports; it is not part of a run.
  • Self-hosted Langfuse v4: dual is the only write mode in which both layouts are selectable, so the optional dual-layout validation above requires it.

Export field reference

Field names and types for each exported file. Types match JSON and JSONL output. Timestamps use YYYY-MM-DD HH:MM:SS.ffffff in UTC. Each schema is collapsed on its own belowโ€”open the file you need.

FileWhen it is exportedSchema
observations_v2/Current enriched exportEnriched observations
scores/Every exportScores
traces/Deprecated legacy exportLegacy exports
observations/Deprecated legacy exportLegacy exports
Enriched observations โ€” observations_v2/

Each row represents one observation and includes its trace context. Only the selected field groups appear; core is always included.

FieldTypeDescription
idstringUnique observation identifier.
trace_idstringTrace identifier shared by related observations and scores.
project_idstringLangfuse project identifier.
environmentstringEnvironment label.
typestringObservation type: SPAN, GENERATION, EVENT, AGENT, TOOL, CHAIN, RETRIEVER, EVALUATOR, EMBEDDING, or GUARDRAIL.
parent_observation_idstringParent observation identifier; empty for a root observation.
is_root_observationbooleanWhether the observation is a logical root.
start_timestring (timestamp)When the observation started.
end_timestring (timestamp) or nullWhen the observation ended.
namestringUser-defined observation name.
metadataobjectUser-supplied observation metadata.
levelstringDEBUG, DEFAULT, WARNING, or ERROR.
status_messagestringStatus or error message.
versionstringUser-defined version.
inputstringObservation input; may contain plain text or JSON.
outputstringObservation output; may contain plain text or JSON.
provided_model_namestringModel name supplied by the SDK or user.
model_parametersstringModel parameters encoded as JSON.
usage_detailsobject (string โ†’ integer)Token usage by category, such as input, output, and total.
cost_detailsobject (string โ†’ number)Cost in USD by category.
completion_start_timestring (timestamp) or nullWhen the first streamed token was generated.
prompt_namestringLangfuse prompt name.
prompt_versioninteger or nullLangfuse prompt version.
total_costnumberTotal observation cost in USD; 0 when no cost was recorded.
latencynumber or nullDuration in seconds.
time_to_first_tokennumber or nullTime to first token in seconds.
model_idstringMatched Langfuse model definition identifier.
created_atstring (timestamp)Row creation time.
updated_atstring (timestamp)Last row update time.
prompt_idstringLangfuse prompt identifier.
tool_callsarray of stringsTool calls encoded as JSON strings.
tool_call_namesarray of stringsNames of called tools.
tool_definitionsobjectTool or function schemas supplied to the model.
usage_pricing_tier_idstring or nullPricing tier identifier used for cost calculation.
usage_pricing_tier_namestring or nullPricing tier name used for cost calculation.
input_pricestring or nullMatched per-unit input price; omitted from Parquet.
output_pricestring or nullMatched per-unit output price; omitted from Parquet.
total_pricestring or nullMatched flat per-call price; omitted from Parquet.
user_idstringEnd-user identifier from the trace.
session_idstringSession identifier from the trace.
trace_namestringTrace name.
tagsarray of stringsTrace tags.
releasestringTrace release.
bookmarkedbooleanWhether the trace is bookmarked.
publicbooleanWhether the trace is public.

Integrations created on or after 2026-04-01 export latency and time_to_first_token in seconds. Older integrations export these fields in milliseconds for backward compatibility.

Scores โ€” scores/

Scores are always exported. Their fields are not configurable. Scores with data type NUMERIC, BOOLEAN, CATEGORICAL, or TEXT are included; corrections (data type CORRECTION) are not.

FieldTypeDescription
idstringUnique score identifier.
timestampstring (timestamp)Score creation time.
project_idstringLangfuse project identifier.
environmentstringEnvironment label.
trace_idstring or nullAssociated trace identifier.
observation_idstring or nullAssociated observation identifier.
session_idstring or nullAssociated session identifier.
dataset_run_idstring or nullAssociated dataset run identifier.
namestringScore name.
valuenumberNumeric value; TEXT scores use 0.
sourcestringAPI, ANNOTATION, or EVAL.
commentstring or nullOptional comment or evaluator reasoning.
data_typestringNUMERIC, BOOLEAN, CATEGORICAL, or TEXT.
string_valuestring or nullCategory label or text value; null for numeric scores.
created_atstring (timestamp)Row creation time.
updated_atstring (timestamp)Last row update time.
Legacy exports โ€” traces/ and observations/

Legacy exports are deprecated. They split trace context into traces/ and observation data into observations/; consumers join them on trace_id. See upgrade a legacy export before changing a consumer.

Traces (traces/)

The trace file has a fixed schema; field groups do not apply.

FieldTypeDescription
idstringUnique trace identifier.
timestampstring (timestamp)Trace creation time.
namestringUser-defined trace name.
environmentstringEnvironment label.
project_idstringLangfuse project identifier.
metadataobjectTrace metadata.
user_idstring or nullEnd-user identifier.
session_idstring or nullSession identifier.
releasestring or nullApplication release.
versionstring or nullUser-defined version.
publicbooleanWhether the trace is public.
bookmarkedbooleanWhether the trace is bookmarked.
tagsarray of stringsTrace tags.
inputstring or nullTrace input.
outputstring or nullTrace output.
created_atstring (timestamp)Row creation time.
updated_atstring (timestamp)Last row update time.

Legacy trace-level input, output, metadata, timestamp, and version do not have direct equivalents in observations_v2/. Observation fields with the same names contain observation-level data instead.

The trace file does not include total_cost, latency, observations, scores, or html_path.

Observations (observations/)

Each row represents one observation without its trace context; join trace_id to the traces/ file to add it. Only the selected field groups appear; core is always included.

FieldTypeDescription
idstringUnique observation identifier.
trace_idstringTrace identifier shared by related observations and scores.
project_idstringLangfuse project identifier.
environmentstringEnvironment label.
typestringObservation type: SPAN, GENERATION, EVENT, AGENT, TOOL, CHAIN, RETRIEVER, EVALUATOR, EMBEDDING, or GUARDRAIL.
parent_observation_idstring or nullParent observation identifier; null for a root observation.
start_timestring (timestamp)When the observation started.
end_timestring (timestamp) or nullWhen the observation ended.
namestringUser-defined observation name.
metadataobjectUser-supplied observation metadata.
levelstringDEBUG, DEFAULT, WARNING, or ERROR.
status_messagestring or nullStatus or error message.
versionstring or nullUser-defined version.
inputstring or nullObservation input; may contain plain text or JSON.
outputstring or nullObservation output; may contain plain text or JSON.
provided_model_namestring or nullModel name supplied by the SDK or user.
model_parametersstring or nullModel parameters encoded as JSON.
usage_detailsobject (string โ†’ integer)Token usage by category, such as input, output, and total.
cost_detailsobject (string โ†’ number)Cost in USD by category.
completion_start_timestring (timestamp) or nullWhen the first streamed token was generated.
prompt_namestring or nullLangfuse prompt name.
prompt_versioninteger or nullLangfuse prompt version.
total_costnumber or nullTotal observation cost in USD.
latencynumber or nullDuration in seconds.
time_to_first_tokennumber or nullTime to first token in seconds.
model_idstring or nullMatched Langfuse model definition identifier.
created_atstring (timestamp)Row creation time.
updated_atstring (timestamp)Last row update time.
prompt_idstring or nullLangfuse prompt identifier.
tool_callsarray of stringsTool calls encoded as JSON strings.
tool_call_namesarray of stringsNames of called tools.
tool_definitionsobjectTool or function schemas supplied to the model.
usage_pricing_tier_namestring or nullPricing tier name used for cost calculation.
input_pricestring or nullMatched per-unit input price; omitted from Parquet.
output_pricestring or nullMatched per-unit output price; omitted from Parquet.
total_pricestring or nullMatched flat per-call price; omitted from Parquet.

Where a field appears in both observation files it carries the same meaning. Unset values are encoded differently, though: a field that is null above maps to one of three values in observations_v2/ JSON and JSONL output.

Value in observations_v2/Fields
"" (empty string)input, model_id, model_parameters, output, parent_observation_id, prompt_id, prompt_name, provided_model_name, status_message, version
nullcompletion_start_time, end_time, input_price, latency, output_price, prompt_version, time_to_first_token, total_price, usage_pricing_tier_name
0total_cost

Empty strings appear where the v4 events table stores the column as non-nullable. total_cost reads from cost_details['total'], so a 0 there cannot be told apart from a genuine zero cost.

For the field groups that select these columns and how they differ from the enriched export, see what changes in the exported data.

Parquet differences

Parquet uses internal encoding and compression, so gzip does not apply.

Observation files omit input_price, output_price, and total_price. Use cost_details and total_cost for cost data.

Trace and score fields are the same across all formats.

For paths, filenames, and the manifest workflow, see process exports.

FAQ


Was this page helpful?

Last updated on