Mixpanel Worker Integration#
Langfuse exports LLM observability data (traces, generations, scores, events) to Mixpanel on a scheduled basis using a two-stage BullMQ queue pipeline. The integration is enabled per-project and runs on a cron schedule, gated by the QUEUE_CONSUMER_MIXPANEL_INTEGRATION_QUEUE_IS_ENABLED environment variable .
Architecture: Two-Stage Queue Pipeline#
The integration uses two BullMQ queues registered in worker/src/app.ts:
-
MixpanelIntegrationQueue— a cron-triggered scheduler queue. Its processor (mixpanelIntegrationProcessor) callshandleMixpanelIntegrationSchedule(), which queries Prisma for all enabled integrations and enqueues oneMixpanelIntegrationProcessingJobper project. -
MixpanelIntegrationProcessingQueue— the per-project worker queue. Its processor (mixpanelIntegrationProcessingProcessor) callshandleMixpanelIntegrationProjectJob(), which fetches data and sends it to Mixpanel.
Both workers run at concurrency 1. The processing queue adds a BullMQ rate limiter of max 1 job per 10 seconds globally .
Job Deduplication#
The scheduler uses a static jobId composed of ${projectId}-${lastSyncAt.toISOString()} . This prevents the same project from being enqueued twice within the same sync window. Jobs use removeOnFail: true so failed jobs are immediately removed from Redis, unblocking re-queuing on the next cycle .
History: An earlier attempt (PR #11988) appended an hourly suffix to the
jobIdto bypass permanently-stalled jobs, but this broke deduplication by allowing unbounded queue growth. PR #11998 reverted to the staticjobIdapproach and switched toremoveOnFail: trueas the correct fix.
Per-Project Data Export#
handleMixpanelIntegrationProjectJob() builds an executionConfig with a sync window: minTimestamp from lastSyncAt (defaulting to 2000-01-01 if null) and maxTimestamp set to 30 minutes ago . It then runs up to four data streams in parallel via Promise.all depending on the project's exportSource setting :
| Stream | Condition |
|---|---|
| Scores | Always |
| Traces | TRACES_OBSERVATIONS or TRACES_OBSERVATIONS_EVENTS |
| Generations | TRACES_OBSERVATIONS or TRACES_OBSERVATIONS_EVENTS |
| Events | EVENTS or TRACES_OBSERVATIONS_EVENTS |
On success, lastSyncAt is updated in Prisma . On failure, the error is logged and re-thrown so BullMQ can retry .
MixpanelClient: Batching and HTTP#
MixpanelClient is instantiated per data stream. It accumulates events in memory and flushes in chunks of 1,000 events (matching PostHog's flushAt convention, and well within Mixpanel's 2,000-event API limit) . Each flush calls the Mixpanel Import API with:
- gzip compression of the JSON body
- Basic Auth using the project token as username with an empty password
- The target region subdomain (e.g.,
api,api-eu,api-in) in the URL
HTTP error handling: A 400 response is treated as a partial success if num_records_imported > 0; the partial failure is logged as a warning rather than throwing . All other non-2xx responses throw an error .
Note: The current
fetch()call has no explicit timeout. A hung HTTP request will block the stream until BullMQ's stall detection kicks in (see below).
Stall Detection and BullMQ Worker Settings#
The processing worker uses non-default stall settings to tolerate slow HTTP round-trips and CPU wait spikes :
| Setting | Value | Effect |
|---|---|---|
lockDuration | 60,000 ms | Reduces lock-renewal frequency |
stalledInterval | 120,000 ms | Checks for stalled jobs every 2 min |
maxStalledCount | 3 | Up to 3 stall recoveries before moving to failed |
These were introduced in PR #11988 to address integration jobs permanently stalling under high CPU load.
Key Files#
| File | Purpose |
|---|---|
worker/src/queues/mixpanelIntegrationQueue.ts | BullMQ processor definitions |
worker/src/features/mixpanel/handleMixpanelIntegrationSchedule.ts | Scheduler: finds enabled integrations and enqueues jobs |
worker/src/features/mixpanel/handleMixpanelIntegrationProjectJob.ts | Per-project export orchestration |
worker/src/features/mixpanel/mixpanelClient.ts | HTTP client: batching, gzip, auth, error handling |
worker/src/app.ts | Worker registration with concurrency, limiter, and stall settings |