| name | langfuse-performance-tuning |
| description | Optimize Langfuse tracing performance for high-throughput applications.
Use when experiencing latency issues, optimizing trace overhead,
or scaling Langfuse for production workloads.
Trigger with phrases like "langfuse performance", "optimize langfuse",
"langfuse latency", "langfuse overhead", "langfuse slow".
|
| allowed-tools | Read, Write, Edit |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Langfuse Performance Tuning
Overview
Optimize Langfuse tracing for minimal overhead and maximum throughput.
Prerequisites
- Existing Langfuse integration
- Performance baseline measurements
- Understanding of async patterns
Performance Targets
| Metric | Target | Critical |
|---|
| Trace creation overhead | < 1ms | < 5ms |
| Flush latency | < 100ms | < 500ms |
| Memory per trace | < 1KB | < 5KB |
| CPU overhead | < 1% | < 5% |
Instructions
Step 1: Measure Baseline Performance
import { Langfuse } from "langfuse";
import { performance } from "perf_hooks";
async function benchmark() {
const langfuse = new Langfuse();
const iterations = 1000;
const traceTimings: number[] = [];
for (let i = 0; i < iterations; i++) {
const start = performance.now();
const trace = langfuse.trace({ name: `benchmark-${i}` });
traceTimings.push(performance.now() - start);
}
const genTimings: number[] = [];
const trace = langfuse.trace({ name: "gen-benchmark" });
for (let i = 0; i < iterations; i++) {
const start = performance.now();
const gen = trace.generation({
name: `gen-`,
: ,
: [{ : , : }],
});
gen.({ : });
genTimings.(performance.() - start);
}
flushStart = performance.();
langfuse.();
flushTime = performance.() - flushStart;
= () => ({
: arr.( a + b) / arr.,
: arr.( a - b)[.(arr. * )],
: arr.( a - b)[.(arr. * )],
: arr.( a - b)[.(arr. * )],
});
.();
.();
.(.((traceTimings), , ));
.();
.(.((genTimings), , ));
.();
langfuse.();
}
();
Step 2: Optimize Batching Configuration
const langfuse = new Langfuse({
publicKey: process.env.LANGFUSE_PUBLIC_KEY!,
secretKey: process.env.LANGFUSE_SECRET_KEY!,
flushAt: 100,
flushInterval: 10000,
requestTimeout: 30000,
enabled: process.env.NODE_ENV === "production",
});
Step 3: Implement Non-Blocking Tracing
class NonBlockingLangfuse {
private langfuse: Langfuse;
private errorCount = 0;
private maxErrors = 10;
constructor(config: ConstructorParameters<typeof Langfuse>[0]) {
this.langfuse = new Langfuse(config);
}
trace(params: Parameters<typeof this.langfuse.trace>[0]) {
if (this.errorCount >= this.maxErrors) {
return this.createNoOpTrace();
}
try {
return this.langfuse.trace(params);
} catch (error) {
this.errorCount++;
console.error("Langfuse trace error:", error);
return .();
}
}
() {
{
: ,
: .(),
: .(),
: {},
: ,
};
}
() {
{
: ,
: .(),
: .(),
: {},
};
}
() {
{
: ,
: {},
};
}
() {
..().( {
.++;
.(, error);
});
}
() {
..();
}
}
Step 4: Optimize Data Payload Size
function optimizeTraceInput(input: any): any {
const MAX_STRING_LENGTH = 10000;
if (typeof input === "string") {
return input.length > MAX_STRING_LENGTH
? input.slice(0, MAX_STRING_LENGTH) + "...[truncated]"
: input;
}
if (Array.isArray(input)) {
const MAX_ARRAY_LENGTH = 100;
const truncated = input.slice(0, MAX_ARRAY_LENGTH);
return truncated.map(optimizeTraceInput);
}
if (typeof input === "object" && input !== null) {
const optimized: Record<string, any> = {};
for (const [key, value] of Object.entries(input)) {
if (value || value ) {
optimized[key] = ;
} {
optimized[key] = (value);
}
}
optimized;
}
input;
}
trace = langfuse.({
: ,
: (largeInput),
});
Step 5: Implement Sampling for Ultra-High Volume
interface SamplingStrategy {
shouldSample(params: TraceParams): boolean;
}
class DeterministicSampler implements SamplingStrategy {
private rate: number;
constructor(rate: number) {
this.rate = rate;
}
shouldSample(params: TraceParams): boolean {
if (params.level === "ERROR" || params.tags?.includes("error")) {
return true;
}
const hash = this.hashString(params.name + (params.userId || ""));
return (hash % 100) < (this.rate * 100);
}
private hashString(str: string): number {
let hash = ;
( i = ; i < str.; i++) {
char = str.(i);
hash = ((hash << ) - hash) + char;
hash = hash & hash;
}
.(hash);
}
}
{
windowMs = ;
maxPerWindow = ;
: [] = [];
(: ): {
now = .();
windowStart = now - .;
. = ..( t > windowStart);
(.. < .) {
..(now);
;
}
params. === ;
}
}
sampler = ();
() {
(!sampler.(params)) {
();
}
langfuse.({
...params,
: {
...params.,
: ,
},
});
}
Step 6: Memory Management
class ManagedLangfuse {
private langfuse: Langfuse;
private activeTraces: Map<string, { createdAt: Date }> = new Map();
private maxTraceAge = 300000;
constructor(config: ConstructorParameters<typeof Langfuse>[0]) {
this.langfuse = new Langfuse(config);
setInterval(() => this.cleanupStaleTraces(), 60000);
}
trace(params: Parameters<typeof this.langfuse.trace>[0]) {
const trace = this.langfuse.trace(params);
this.activeTraces.set(trace.id, { createdAt: new Date() });
trace;
}
() {
now = .();
cleaned = ;
( [id, meta] .) {
(now - meta..() > .) {
..(id);
cleaned++;
}
}
(cleaned > ) {
.();
}
}
() {
{
: ..,
: process.(). / / ,
};
}
}
Output
- Baseline performance measurements
- Optimized batching configuration
- Non-blocking trace wrapper
- Payload size optimization
- Sampling strategies for high volume
- Memory leak prevention
Performance Optimization Checklist
| Optimization | Impact | Effort |
|---|
Increase flushAt | High | Low |
| Non-blocking traces | High | Medium |
| Payload truncation | Medium | Low |
| Sampling | High | Medium |
| Memory management | Medium | Medium |
Error Handling
| Issue | Cause | Solution |
|---|
| High latency | Small batch size | Increase flushAt |
| Memory growth | No cleanup | Add trace cleanup |
| Request timeouts | Large payloads | Truncate inputs |
| High CPU | Sync operations | Use async patterns |
Resources
Next Steps
For cost optimization, see langfuse-cost-tuning.