Ctrl + K
DocumentationLog inGet started

langfuse-local-dev-loop

tessl install github:jeremylongshore/claude-code-plugins-plus-skills --skill langfuse-local-dev-loop
github.com/jeremylongshore/claude-code-plugins-plus-skills

Set up Langfuse local development workflow with hot reload and debugging. Use when developing LLM applications locally, debugging traces, or setting up a fast iteration loop with Langfuse. Trigger with phrases like "langfuse local dev", "langfuse development", "debug langfuse traces", "langfuse hot reload", "langfuse dev workflow".

Review Score

81%

Validation Score

12/16

Implementation Score

73%

Activation Score

90%

Langfuse Local Dev Loop

Overview

Set up a fast, iterative local development workflow with Langfuse tracing and debugging.

Prerequisites

  • Completed langfuse-install-auth setup
  • Node.js 18+ or Python 3.9+
  • Docker (optional, for self-hosted local instance)
  • IDE with TypeScript/Python support

Instructions

Step 1: Configure Development Environment

Create a .env.local file for development-specific settings:

# .env.local
LANGFUSE_PUBLIC_KEY=pk-lf-dev-...
LANGFUSE_SECRET_KEY=sk-lf-dev-...
LANGFUSE_HOST=https://cloud.langfuse.com

# Development options
LANGFUSE_DEBUG=true
LANGFUSE_FLUSH_AT=1        # Flush after every event for immediate visibility
LANGFUSE_FLUSH_INTERVAL=1000  # Flush every second

Step 2: Create Debug-Enabled Client

// src/lib/langfuse.ts
import { Langfuse } from "langfuse";

const isDev = process.env.NODE_ENV !== "production";

export const langfuse = new Langfuse({
  publicKey: process.env.LANGFUSE_PUBLIC_KEY!,
  secretKey: process.env.LANGFUSE_SECRET_KEY!,
  baseUrl: process.env.LANGFUSE_HOST,
  // Development settings
  flushAt: isDev ? 1 : 15,
  flushInterval: isDev ? 1000 : 10000,
  // Enable debug logging in dev
  ...(isDev && {
    debug: true,
  }),
});

// Auto-flush on process exit
process.on("beforeExit", async () => {
  await langfuse.shutdownAsync();
});

// Helper to get trace URL immediately
export function logTraceUrl(trace: ReturnType<typeof langfuse.trace>) {
  if (isDev) {
    console.log(`\nπŸ” Trace: ${trace.getTraceUrl()}\n`);
  }
}

Step 3: Set Up Hot Reload Development Script

// package.json
{
  "scripts": {
    "dev": "tsx watch --env-file=.env.local src/index.ts",
    "dev:debug": "DEBUG=langfuse* tsx watch --env-file=.env.local src/index.ts"
  }
}

Step 4: Add Development Utilities

// src/lib/dev-utils.ts
import { langfuse, logTraceUrl } from "./langfuse";

// Wrapper that logs trace URLs in dev
export function withTracing<T extends (...args: any[]) => Promise<any>>(
  name: string,
  fn: T
): T {
  return (async (...args: Parameters<T>) => {
    const trace = langfuse.trace({
      name,
      input: args,
      tags: ["dev"],
    });

    logTraceUrl(trace);

    try {
      const result = await fn(...args);
      trace.update({ output: result });
      return result;
    } catch (error) {
      trace.update({
        output: { error: String(error) },
        tags: ["dev", "error"],
      });
      throw error;
    }
  }) as T;
}

// Quick debug trace
export function debugTrace(name: string, data: Record<string, any>) {
  const trace = langfuse.trace({
    name: `debug/${name}`,
    metadata: data,
    tags: ["debug"],
  });
  logTraceUrl(trace);
  return trace;
}

Local Self-Hosted Instance (Optional)

For completely local development without cloud:

# docker-compose.langfuse.yml
version: "3.8"
services:
  langfuse:
    image: langfuse/langfuse:latest
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/langfuse
      - NEXTAUTH_SECRET=development-secret-change-in-prod
      - NEXTAUTH_URL=http://localhost:3000
      - SALT=development-salt-change-in-prod
    depends_on:
      - db

  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=langfuse
    volumes:
      - langfuse-db:/var/lib/postgresql/data

volumes:
  langfuse-db:
# Start local Langfuse
docker compose -f docker-compose.langfuse.yml up -d

# Update .env.local
echo 'LANGFUSE_HOST=http://localhost:3000' >> .env.local

Output

  • Development environment with hot reload
  • Immediate trace visibility (flush after every event)
  • Debug logging enabled
  • Trace URLs printed to console
  • (Optional) Local Langfuse instance

Error Handling

IssueCauseSolution
Traces delayedBatching enabledSet flushAt: 1 in dev
No debug outputDebug not enabledSet LANGFUSE_DEBUG=true
Hot reload failsFile watching issueUse tsx watch or nodemon
Local instance unreachableDocker not runningRun docker compose up -d

Examples

Quick Development Test

// src/index.ts
import { langfuse, logTraceUrl } from "./lib/langfuse";
import OpenAI from "openai";
import { observeOpenAI } from "langfuse";

const openai = observeOpenAI(new OpenAI());

async function devTest() {
  const trace = langfuse.trace({
    name: "dev-test",
    tags: ["dev"],
  });

  logTraceUrl(trace);

  const response = await openai.chat.completions.create(
    {
      model: "gpt-4",
      messages: [{ role: "user", content: "Hello!" }],
    },
    { langfuseParent: trace }
  );

  console.log("Response:", response.choices[0].message.content);
  await langfuse.flushAsync();
}

devTest();

Watch Mode with Live Trace Links

# Terminal output with trace links
$ pnpm dev

πŸ”„ Watching for changes...

πŸ” Trace: https://cloud.langfuse.com/trace/abc123...

Response: Hello! How can I help you today?

[File changed, reloading...]

πŸ” Trace: https://cloud.langfuse.com/trace/def456...

Response: I'm doing great, thanks for asking!

Debug Mode Configuration

// Enable verbose SDK debugging
const langfuse = new Langfuse({
  publicKey: process.env.LANGFUSE_PUBLIC_KEY!,
  secretKey: process.env.LANGFUSE_SECRET_KEY!,
  debug: true, // Logs all SDK operations
});

// Or use environment variable
// DEBUG=langfuse* pnpm dev

Resources

  • Langfuse Local Development
  • Langfuse Self-Hosting
  • Langfuse Docker Image

Next Steps

For SDK patterns and best practices, see langfuse-sdk-patterns.