Dosu LogoDosu Logo
Ask
Join our Discord
langfuse/langfusePublic
Langfuse
Documentslangfuse/langfuse
Webhook Reliability
Webhook Reliability
Type
Topic
Status
Published
Created
Aug 10, 2026
Updated
Aug 10, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

Webhook Reliability: Admin Access Webhook#

Overview#

The admin access webhook (adminAccessWebhook.ts) fires an HTTP notification whenever a Langfuse admin user accesses a project or trace they are not a member of. It is configured via the LANGFUSE_ADMIN_ACCESS_WEBHOOK environment variable. The webhook call is fire-and-forget: errors are logged but never surfaced to the caller.

Key Files#

FilePurpose
web/src/server/adminAccessWebhook.tsCore send logic + dedupe cache
web/src/server/api/trpc.tstRPC middleware that calls the webhook
web/src/__tests__/async/admin-access-webhook.servertest.tsUnit tests for sendAdminAccessWebhook
web/src/__tests__/server/admin-access-webhook-middleware.servertest.tsIntegration tests for middleware

How It Works#

sendAdminAccessWebhook is called from three tRPC authorization middlewares in trpc.ts:

  • enforceUserIsAuthedAndProjectMember — fires when an admin accesses a project they are not a session member of , and also when the admin is a session member .
  • enforceTraceAccess — fires when an admin accesses any trace .
  • enforceSessionAccess — fires when an admin accesses any trace session .

These map to the exported procedures protectedProjectProcedure, protectedGetTraceProcedure, and protectedGetSessionProcedure .

Known Reliability Issues#

1. Deduplication Timing Bug#

The dedupe key is recorded in lastWebhookByKey before the fetch call completes . If the POST request fails (network error, timeout, non-2xx response), the dedup window is still consumed — subsequent calls within the 5-minute window are silently dropped without retrying. The dedup window is hardcoded to 5 minutes . The correct fix is to record the key only after a successful response.

2. Missing Fetch Timeout#

fetch is called with no signal / AbortController timeout . If the webhook endpoint is unresponsive, the await fetch(...) hangs indefinitely. Because sendAdminAccessWebhook is await-ed inside the tRPC authorization middleware before next() is called, a hung fetch will stall every middleware execution and block the request for the full lifecycle of the TCP connection — potentially exhausting the Node.js event loop under load.

3. Test Coverage Gaps#

The existing test suite covers normal flow and basic error paths , but does not exercise:

  • The dedupe timing bug: no test verifies that a failed fetch does not consume the dedupe window.
  • Fetch timeout behavior: no test simulates a hanging fetch or asserts that the middleware resolves within a bounded time.
  • The enforceIsAuthedAndOrgMember path (org-level admin access webhook) is not covered by the middleware integration tests .

Deduplication Details#

The dedup key is email:project:org . The cache (lastWebhookByKey) is a module-level Map — it is process-local and does not survive restarts or span multiple server instances. resetAdminAccessWebhookCacheForTests() is exposed for test teardown .

Webhook Payload Shape#

type AdminAccessWebhookPayload = {
  email: string;
  timestamp: string; // ISO 8601
  project: string | null;
  org: string | null;
  region: string; // NEXT_PUBLIC_LANGFUSE_CLOUD_REGION or "self-hosted"
};

Suggested Fixes#

  1. Dedupe after success: Move lastWebhookByKey.set(...) inside the try block, after confirming response.ok.
  2. Add a fetch timeout: Wrap the fetch call with an AbortSignal.timeout(...) (Node 18+) to bound the maximum wait.
  3. Add regression tests: Test that a failed fetch does not block re-sends within the dedupe window, and that the middleware does not hang when fetch never resolves.
Documents
Agent Sandbox Runtime
Annotation Form Components
API Key Management
Authentication Email Handling
Background Migration Timeout Configuration
BullMQ Worker Lifecycle
Chat Prompt Configuration
ChatML Message Rendering
CJK Input and Unicode Handling
ClickHouse Backfill
ClickHouse Full-Text Search
ClickHouse Migrations
ClickHouse Query Design
ClickHouse Query Execution
ClickHouse Version Compatibility
Dashboard Chart Rendering
Dashboard Query Backend Architecture
Data Masking
Database Upsert and Uniqueness Constraints
Dataset Item Processing Pipeline
Eval Job Execution
Eval Output Schema
Eval Template Versioning
Evaluation Queue Architecture
Evaluator Configuration and Status Management
Events Table Architecture
Events Table Query Routing
Experiments
Filter State Management
HTTP Proxy Configuration
Lambda MicroVM Sandbox
LangGraph Integration
LLM Model Configuration
LLM-as-a-Judge Evaluation
Lossless JSON Parsing
MCP Server Integration
MCP Tool Schema Design
Mixpanel Worker Integration
Model Pricing Configuration
NextAuth OAuth Integration
Observation Data Loading
Observation Eval Scheduling
Onboarding State Management
OTel Attribute Serialization
OTel GenAI Message Ingestion
OTel Ingestion and Trace Hierarchy
OTel Token Usage Processing
Redis Client Management
Redis Retry Strategy
Redis Sentinel Integration
Score Configuration Management
Self-Hosted Deployment
Token Usage Enrichment
Token Usage Storage
Trace Heatmap Visualization
Trace-Level Token Aggregation
Usage Cost Calculation
V4 Data Pipeline Migration
Webhook Reliability