Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Langfuse Langfuse PromptService Cache

From Leeroopedia
Knowledge Sources
Domains Prompt Management, Caching, Distributed Systems
Last Updated 2026-02-14 00:00 GMT

Overview

Concrete tool for Redis-based prompt cache locking, invalidation, and lifecycle management provided by Langfuse.

Description

The PromptService class exposes three public cache management methods -- lockCache, unlockCache, and invalidateCache -- that together implement the lock-invalidate-unlock protocol for safe prompt mutations.

lockCache sets a Redis key with a 30-second TTL that signals to all read operations that the cache is currently being mutated. While the lock is held, getPrompt bypasses the cache entirely and reads from the database.

unlockCache deletes the lock key, re-enabling cache reads. If the delete fails, the error is logged but not re-thrown, relying on the 30-second TTL as a safety net.

invalidateCache uses a key index pattern (a Redis Set that tracks all cache keys for a project) to perform bulk deletion of all cached prompt entries. It also handles legacy key index migration by deleting entries stored under the old per-prompt-name key index format.

Supporting these public methods are several private helpers: isCacheLocked checks for the existence of the lock key, getCachedPrompt reads and deserializes a cached prompt (refreshing its TTL), cachePrompt serializes and stores a prompt result, and the key generation methods (getCacheKey, getCacheKeyPrefix, getKeyIndexKey, getLockKey) construct the appropriate Redis keys.

Usage

These methods are called internally by the createPrompt function (and other prompt mutation operations). The lock is acquired before the database transaction, invalidation happens immediately after locking, the database write occurs, and then the lock is released. Application developers typically do not call these methods directly; they are part of the PromptService infrastructure.

Code Reference

Source Location

  • Repository: langfuse
  • File: packages/shared/src/server/services/PromptService/index.ts
  • Lines: 175-254 (lockCache, unlockCache, invalidateCache) with supporting private methods throughout the class

Signature

// Lock: prevents cache reads during mutation
public async lockCache(
  params: Pick<PromptParams, "projectId" | "promptName">,
): Promise<void>

// Unlock: re-enables cache reads
public async unlockCache(
  params: Pick<PromptParams, "projectId" | "promptName">,
): Promise<void>

// Invalidate: bulk-delete all cached prompts for a project
public async invalidateCache(
  params: Pick<PromptParams, "projectId" | "promptName">,
): Promise<void>

// Private: check lock status
private async isCacheLocked(
  params: Pick<PromptParams, "projectId" | "promptName">,
): Promise<boolean>

// Private: read from cache with TTL refresh
private async getCachedPrompt(
  params: PromptParams,
): Promise<PromptResult | null>

// Private: write to cache
private async cachePrompt(
  params: PromptParams & { prompt: PromptResult },
): Promise<void>

Import

import { PromptService } from "@langfuse/shared/src/server";

I/O Contract

Inputs (lockCache / unlockCache / invalidateCache)

Name Type Required Description
projectId string Yes The project ID whose prompt cache should be locked/unlocked/invalidated.
promptName string Yes The prompt name. Used by invalidateCache for legacy key index cleanup. The lock itself is scoped to the project level (not per prompt name).

Outputs (lockCache)

Name Type Description
void void Sets the Redis lock key. If caching is disabled, returns immediately without side effects. Throws on Redis errors (lock acquisition is critical).

Outputs (unlockCache)

Name Type Description
void void Deletes the Redis lock key. If caching is disabled, returns immediately. Does NOT throw on Redis errors (lock has TTL safety net).

Outputs (invalidateCache)

Name Type Description
void void Deletes all cached prompt entries for the project from Redis using the key index, plus deletes the key index itself and any legacy-format key index entries.

Redis Key Patterns

Key Type Pattern Example Description
Cache Key prompt:{projectId}:{promptName}:{version|label} prompt:proj_abc:my-prompt:3 Stores a serialized PromptResult for a specific version or label.
Key Index prompt_key_index:{projectId} prompt_key_index:proj_abc Redis Set tracking all cache keys for bulk deletion.
Legacy Key Index prompt_key_index:{projectId}:{promptName} prompt_key_index:proj_abc:my-prompt Old format; cleaned up during invalidation for backwards compatibility.
Lock Key LOCK:prompt:{projectId} LOCK:prompt:proj_abc Signals that a mutation is in progress. TTL: 30 seconds.

Usage Examples

Lock-Invalidate-Unlock During Prompt Creation

import { PromptService } from "@langfuse/shared/src/server";

const promptService = new PromptService(prisma, redis);

// Phase 1: Lock cache to prevent stale reads
await promptService.lockCache({
  projectId: "proj_abc123",
  promptName: "my-prompt",
});

// Phase 2: Invalidate all cached versions
await promptService.invalidateCache({
  projectId: "proj_abc123",
  promptName: "my-prompt",
});

// Phase 3: Perform database mutation (transaction)
const [createdPrompt] = await prisma.$transaction([
  prisma.prompt.create({ data: { /* ... */ } }),
]);

// Phase 4: Unlock cache to allow fresh reads
await promptService.unlockCache({
  projectId: "proj_abc123",
  promptName: "my-prompt",
});

Cache Behavior During Lock

// While the lock is held, getPrompt bypasses cache:
const result = await promptService.getPrompt({
  projectId: "proj_abc123",
  promptName: "my-prompt",
  label: "production",
  version: undefined,
});
// This reads directly from PostgreSQL, not from Redis.
// After unlock, subsequent calls will repopulate the cache.

PromptService Constructor Configuration

// Caching is enabled when:
// 1. A Redis client is provided (not null)
// 2. The LANGFUSE_CACHE_PROMPT_ENABLED env var is "true"
const promptService = new PromptService(
  prisma,          // PrismaClient
  redis,           // Redis | Cluster | null
  metricFn,        // Optional: (name: string, value?: number) => void
  true,            // Optional: override cacheEnabled for testing
);

// TTL is configured via LANGFUSE_CACHE_PROMPT_TTL_SECONDS environment variable

Related Pages

Implements Principle

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment