Claude-code-plugins-plus-skills langfuse-multi-env-setup
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/langfuse-pack/skills/langfuse-multi-env-setup" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-langfuse-multi-env-setup && rm -rf "$T"
manifest:
plugins/saas-packs/langfuse-pack/skills/langfuse-multi-env-setup/SKILL.mdsource content
Langfuse Multi-Environment Setup
Overview
Configure Langfuse across dev/staging/production with isolated API keys, environment-specific SDK settings, secret management, and CI/CD integration to prevent cross-environment data leakage.
Prerequisites
- Separate Langfuse API key pairs per environment (or separate projects)
- Secret management solution (env vars, Vault, AWS/GCP secrets)
- CI/CD pipeline with environment-aware deployment
Environment Strategy
| Environment | API Key Source | Langfuse Project | Settings |
|---|---|---|---|
| Development | | Dev project | Debug on, flush immediately, 100% sampling |
| Staging | CI/CD secrets | Staging project | Prod-like settings, 50% sampling |
| Production | Secret manager | Prod project | Optimized batching, 10% sampling |
Instructions
Step 1: Environment-Specific Configuration
// src/config/langfuse.ts import { LangfuseSpanProcessor } from "@langfuse/otel"; import { NodeSDK } from "@opentelemetry/sdk-node"; import { LangfuseClient } from "@langfuse/client"; type Env = "development" | "staging" | "production"; interface LangfuseEnvConfig { exportIntervalMillis: number; maxExportBatchSize: number; debug: boolean; sampleRate: number; } const ENV_CONFIGS: Record<Env, LangfuseEnvConfig> = { development: { exportIntervalMillis: 1000, maxExportBatchSize: 1, debug: true, sampleRate: 1.0, }, staging: { exportIntervalMillis: 5000, maxExportBatchSize: 25, debug: false, sampleRate: 0.5, }, production: { exportIntervalMillis: 10000, maxExportBatchSize: 50, debug: false, sampleRate: 0.1, }, }; function detectEnvironment(): Env { const env = process.env.NODE_ENV || "development"; if (env === "production") return "production"; if (env === "staging" || process.env.VERCEL_ENV === "preview") return "staging"; return "development"; } export function initLangfuse() { const env = detectEnvironment(); const config = ENV_CONFIGS[env]; // Validate credentials const required = ["LANGFUSE_PUBLIC_KEY", "LANGFUSE_SECRET_KEY"]; for (const key of required) { if (!process.env[key]) { throw new Error(`${key} not set for environment: ${env}`); } } // Initialize OTel with env-specific settings const processor = new LangfuseSpanProcessor({ exportIntervalMillis: config.exportIntervalMillis, maxExportBatchSize: config.maxExportBatchSize, }); const sdk = new NodeSDK({ spanProcessors: [processor] }); sdk.start(); // Client for prompts, datasets, scores const client = new LangfuseClient(); console.log(`Langfuse initialized [${env}] (sample: ${config.sampleRate * 100}%)`); return { sdk, client, env, config }; }
Step 2: Environment Variable Files
# .env.local (development -- git-ignored) LANGFUSE_PUBLIC_KEY=pk-lf-dev-... LANGFUSE_SECRET_KEY=sk-lf-dev-... LANGFUSE_BASE_URL=https://cloud.langfuse.com NODE_ENV=development # .env.staging (used by CI/CD) LANGFUSE_BASE_URL=https://cloud.langfuse.com NODE_ENV=staging # Keys injected via CI secrets # .env.production (used by CI/CD) LANGFUSE_BASE_URL=https://cloud.langfuse.com NODE_ENV=production # Keys injected via secret manager
# .gitignore .env .env.local .env.*.local
Step 3: Secret Management
set -euo pipefail # GitHub Actions: Add per-environment secrets # Settings > Environments > staging > Secrets # Settings > Environments > production > Secrets # AWS Secrets Manager aws secretsmanager create-secret \ --name "langfuse/production/public-key" \ --secret-string "pk-lf-prod-..." aws secretsmanager create-secret \ --name "langfuse/production/secret-key" \ --secret-string "sk-lf-prod-..." # GCP Secret Manager echo -n "pk-lf-prod-..." | gcloud secrets create langfuse-public-key-prod --data-file=- echo -n "sk-lf-prod-..." | gcloud secrets create langfuse-secret-key-prod --data-file=-
Step 4: CI/CD Integration
# .github/workflows/deploy.yml name: Deploy on: push: branches: [main, staging] jobs: deploy-staging: if: github.ref == 'refs/heads/staging' runs-on: ubuntu-latest environment: staging env: LANGFUSE_PUBLIC_KEY: ${{ secrets.LANGFUSE_PUBLIC_KEY }} LANGFUSE_SECRET_KEY: ${{ secrets.LANGFUSE_SECRET_KEY }} LANGFUSE_BASE_URL: https://cloud.langfuse.com NODE_ENV: staging steps: - uses: actions/checkout@v4 - run: npm ci && npm run build && npm run deploy:staging deploy-production: if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: production env: LANGFUSE_PUBLIC_KEY: ${{ secrets.LANGFUSE_PUBLIC_KEY }} LANGFUSE_SECRET_KEY: ${{ secrets.LANGFUSE_SECRET_KEY }} LANGFUSE_BASE_URL: https://cloud.langfuse.com NODE_ENV: production steps: - uses: actions/checkout@v4 - run: npm ci && npm run build && npm run deploy:production
Step 5: Startup Validation with Zod
import { z } from "zod"; const langfuseConfigSchema = z.object({ LANGFUSE_PUBLIC_KEY: z.string().startsWith("pk-lf-", "Must start with pk-lf-"), LANGFUSE_SECRET_KEY: z.string().startsWith("sk-lf-", "Must start with sk-lf-"), LANGFUSE_BASE_URL: z.string().url().optional(), NODE_ENV: z.enum(["development", "staging", "production"]).default("development"), }); // Validate at startup -- fail fast on misconfiguration const config = langfuseConfigSchema.parse(process.env); console.log(`Langfuse config validated for ${config.NODE_ENV}`);
Cross-Environment Safety
| Risk | Mitigation |
|---|---|
| Dev traces in prod project | Separate API keys per environment |
| Prod keys in dev env | Validate key prefix at startup |
| Leaked keys in git | in , secret scanning in CI |
| Wrong env detected | Explicit in deployment config |
| Config drift | Zod schema validation at startup |
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Wrong environment | Missing | Set explicitly in deployment config |
| Secret not found | Wrong secret path | Verify secret manager paths match |
| Cross-env data leak | Shared API key | Use separate keys per environment |
| Startup crash | Missing config | Add Zod validation with clear error messages |