| name | langfuse-data-handling |
| description | Manage Langfuse data export, retention, and compliance requirements.
Use when exporting trace data, configuring retention policies,
or implementing data compliance for LLM observability.
Trigger with phrases like "langfuse data export", "langfuse retention",
"langfuse GDPR", "langfuse compliance", "export langfuse traces".
|
| allowed-tools | Read, Write, Edit |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Langfuse Data Handling
Overview
Manage Langfuse data lifecycle including export, retention, and compliance.
Prerequisites
- Langfuse account with data access
- Understanding of data retention requirements
- Compliance framework knowledge (GDPR, SOC2, etc.)
Data Categories
| Category | Examples | Retention | Sensitivity |
|---|
| Traces | Operation metadata | 90 days | Medium |
| Generations | LLM inputs/outputs | 30-90 days | High |
| Scores | Evaluation results | 1 year | Low |
| Sessions | User interactions | 90 days | High |
| Metrics | Aggregated stats | 2 years | Low |
Instructions
Step 1: Export Trace Data via API
import { Langfuse } from "langfuse";
import fs from "fs/promises";
interface ExportOptions {
fromDate: Date;
toDate: Date;
format: "json" | "csv";
includeInputs: boolean;
includeOutputs: boolean;
}
async function exportTraces(options: ExportOptions) {
const langfuse = new Langfuse();
let page = 1;
const pageSize = 100;
const allTraces: any[] = [];
while (true) {
const response = await langfuse.fetchTraces({
fromTimestamp: options.fromDate,
toTimestamp: options.toDate,
limit: pageSize,
page,
});
if (response.data.length === 0) break;
( trace response.) {
exportedTrace = {
: trace.,
: trace.,
: trace.,
: trace.,
: trace.,
: trace.,
: trace.,
...(options. && { : trace. }),
...(options. && { : trace. }),
};
allTraces.(exportedTrace);
}
page++;
( (r, ));
}
filename = ;
(options. === ) {
fs.(, .(allTraces, , ));
} {
csv = (allTraces);
fs.(, csv);
}
{
filename,
: allTraces.,
};
}
(): {
(data. === ) ;
headers = .(data[]);
rows = data.(
headers.( .(item[h] ?? )).()
);
[headers.(), ...rows].();
}
Step 2: Implement Data Retention Policy
import { Langfuse } from "langfuse";
interface RetentionPolicy {
defaultRetentionDays: number;
traceRetentionDays: number;
generationRetentionDays: number;
scoreRetentionDays: number;
piiRetentionDays: number;
}
const DEFAULT_POLICY: RetentionPolicy = {
defaultRetentionDays: 90,
traceRetentionDays: 90,
generationRetentionDays: 30,
scoreRetentionDays: 365,
piiRetentionDays: 30,
};
async function applyRetentionPolicy(policy: RetentionPolicy = DEFAULT_POLICY) {
const langfuse = new Langfuse();
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - policy.traceRetentionDays);
oldTraces = langfuse.({
: cutoffDate,
: ,
});
.();
{
: oldTraces..,
cutoffDate,
};
}
Step 3: Implement GDPR Data Subject Requests
interface DataSubjectRequest {
type: "access" | "deletion" | "rectification";
userId: string;
requestId: string;
requestedAt: Date;
}
async function handleDataAccessRequest(userId: string): Promise<any> {
const langfuse = new Langfuse();
const traces = await langfuse.fetchTraces({
userId,
limit: 10000,
});
const userData = {
requestType: "GDPR Data Access",
userId,
generatedAt: new Date().toISOString(),
data: {
traces: traces.data.map((trace) => ({
id: trace.id,
timestamp: trace.timestamp,
name: trace.name,
sessionId: trace.,
: ,
: ,
})),
: traces..,
},
};
userData;
}
(): <> {
langfuse = ();
traces = langfuse.({
userId,
: ,
});
deletionRecord = {
: ,
userId,
: ().(),
: traces..,
: ,
};
.(, deletionRecord);
deletionRecord;
}
(): <> {
auditLog = {
: request.,
: request.,
: request.,
: request..(),
: ().(),
};
(request.) {
:
{
...auditLog,
: (request.),
};
:
{
...auditLog,
: (request.),
};
:
{
...auditLog,
: ,
: ,
};
}
}
Step 4: Implement Data Anonymization
interface AnonymizationConfig {
hashUserId: boolean;
removeInputs: boolean;
removeOutputs: boolean;
removeMetadataFields: string[];
}
function anonymizeTrace(
trace: any,
config: AnonymizationConfig = {
hashUserId: true,
removeInputs: false,
removeOutputs: false,
removeMetadataFields: ["email", "name", "phone"],
}
): any {
const anonymized = { ...trace };
if (config.hashUserId && anonymized.userId) {
anonymized.userId = hashString(anonymized.userId);
anonymized.sessionId = anonymized.sessionId
? hashString(anonymized.sessionId)
: null;
}
if (config.removeInputs) {
anonymized.input = "[REDACTED]";
}
if (config.removeOutputs) {
anonymized.output = "[REDACTED]";
}
(anonymized.) {
( field config.) {
anonymized.[field];
}
}
anonymized;
}
(): {
crypto = ();
crypto.().(str).().(, );
}
(): <[]> {
langfuse = ();
traces = langfuse.({
: fromDate,
: toDate,
: ,
});
traces..(
(trace, {
: ,
: ,
: ,
: [, , , ],
})
);
}
Step 5: Create Audit Trail
interface AuditEvent {
timestamp: Date;
action: string;
actor: string;
resource: string;
details: Record<string, any>;
result: "success" | "failure";
}
class AuditLogger {
private events: AuditEvent[] = [];
log(event: Omit<AuditEvent, "timestamp">) {
const auditEvent: AuditEvent = {
...event,
timestamp: new Date(),
};
this.events.push(auditEvent);
this.persist(auditEvent);
}
private async persist(event: AuditEvent) {
const logLine = JSON.stringify(event) + "\n";
fs.(, logLine);
}
(: {
?: ;
?: ;
?: ;
?: ;
}): <[]> {
content = fs.(, );
events = content
.()
.()
.( .(line));
(options.) {
events = events.( (e.) >= options.!);
}
(options.) {
events = events.( (e.) <= options.!);
}
(options.) {
events = events.( e. === options.);
}
(options.) {
events = events.( e. === options.);
}
events;
}
}
auditLogger = ();
auditLogger.({
: ,
: ,
: ,
: { : , : },
: ,
});
Output
- Data export functionality (JSON/CSV)
- Retention policy implementation
- GDPR compliance handlers
- Data anonymization
- Audit trail logging
Compliance Checklist
| Requirement | Implementation | Status |
|---|
| Data inventory | Track what data is collected | [ ] |
| Retention limits | Auto-delete old data | [ ] |
| Access requests | Export user data | [ ] |
| Deletion requests | Remove user data | [ ] |
| Anonymization | Hash/redact PII | [ ] |
| Audit trail | Log all data access | [ ] |
| Encryption | TLS in transit, at rest | [ ] |
Error Handling
| Issue | Cause | Solution |
|---|
| Export timeout | Too much data | Use pagination |
| Missing user data | Wrong userId format | Verify identifier |
| Deletion failed | No DB access | Contact Langfuse support |
| Audit gaps | Async logging | Use sync logging for critical |
Resources
Next Steps
For enterprise RBAC, see langfuse-enterprise-rbac.