<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Acrux Core</title>
    <description>The latest articles on DEV Community by Acrux Core (@acruxcore).</description>
    <link>https://dev.to/acruxcore</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4066131%2F08f6e2ff-d468-4464-86f3-2d794860767a.jpg</url>
      <title>DEV Community: Acrux Core</title>
      <link>https://dev.to/acruxcore</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/acruxcore"/>
    <language>en</language>
    <item>
      <title>Langfuse vs Acrux Core: the same prompt, run for real on both</title>
      <dc:creator>Acrux Core</dc:creator>
      <pubDate>Thu, 06 Aug 2026 15:08:46 +0000</pubDate>
      <link>https://dev.to/acruxcore/langfuse-vs-acrux-core-the-same-prompt-run-for-real-on-both-1mg3</link>
      <guid>https://dev.to/acruxcore/langfuse-vs-acrux-core-the-same-prompt-run-for-real-on-both-1mg3</guid>
      <description>&lt;p&gt;Langfuse is the LLM-ops platform we get compared to most often, and it deserves a real&lt;br&gt;
answer, not a table copied from two docs sites. So we built the same prompt —&lt;br&gt;
&lt;code&gt;vip-support-triage&lt;/code&gt;, a support agent that changes tone for VIP customers and lists&lt;br&gt;
their open tickets — on both platforms, then ran the identical sequence on each: create&lt;br&gt;
the prompt, version it, send a live call, inspect the trace, build a dataset, run an&lt;br&gt;
experiment, and call it from an SDK script. Both products are open source today, so this&lt;br&gt;
isn't about who's open — it's about what each one is actually shaped like.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Same example, both sides.&lt;/strong&gt; Every paired screenshot below comes from the exact same&lt;br&gt;
prompt and the exact same customer message, sent through the exact same downstream&lt;br&gt;
model (&lt;code&gt;openai/gpt-4o-mini&lt;/code&gt; via OpenRouter) on both platforms. Where a step is&lt;br&gt;
genuinely one-sided — no equivalent screen exists on the other product — we say so&lt;br&gt;
instead of padding it out.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  1. Prompt authoring &amp;amp; versioning
&lt;/h2&gt;

&lt;p&gt;Acrux Core's editor uses &lt;strong&gt;nunjucks&lt;/strong&gt; — real &lt;code&gt;{% if %}&lt;/code&gt; and &lt;code&gt;{% for %}&lt;/code&gt; logic, so the&lt;br&gt;
VIP branch and the ticket list live in the template itself. Langfuse's templating is&lt;br&gt;
flat &lt;code&gt;{{variable}}&lt;/code&gt; substitution only, so we had to pre-render the VIP note and the&lt;br&gt;
ticket list into plain strings before the prompt ever saw them — Langfuse's own commit&lt;br&gt;
message on the recreated prompt says so explicitly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnq1p5an6hg4qjletik37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnq1p5an6hg4qjletik37.png" alt="Langfuse's create-prompt screen for the recreated vip-support-triage prompt, with a commit message noting it was adapted from Acrux Core's nunjucks template since Langfuse only supports flat variable substitution" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu0jpp0ykftk5em3mnv8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu0jpp0ykftk5em3mnv8s.png" alt="Langfuse's prompt versions list showing a single version — no diff or compare control anywhere in the version history UI" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpu61tgohhhrf3tfbsfh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpu61tgohhhrf3tfbsfh0.png" alt="Acrux Core's prompt editor showing the real nunjucks conditional and loop syntax rendering VIP status and the ticket list inline" width="799" height="571"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc5d72oedslrcq7v5rwdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc5d72oedslrcq7v5rwdk.png" alt="Acrux Core's Diff tab showing a real unified diff between prompt version 2 and version 3" width="799" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Conditional templating&lt;/td&gt;
&lt;td&gt;Flat &lt;code&gt;{{variable}}&lt;/code&gt; only — verified hands-on, no &lt;code&gt;{% if %}&lt;/code&gt;/&lt;code&gt;{% for %}&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Real nunjucks &lt;code&gt;{% if %}&lt;/code&gt;/&lt;code&gt;{% for %}&lt;/code&gt;, rendered server-side&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Version comparison&lt;/td&gt;
&lt;td&gt;No diff/compare control found in the version history UI&lt;/td&gt;
&lt;td&gt;Standing &lt;strong&gt;Diff&lt;/strong&gt; tab, unified diff between any two versions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live/staging labels&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;production&lt;/code&gt; / &lt;code&gt;latest&lt;/code&gt; labels on a version&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;production&lt;/code&gt; / &lt;code&gt;staging&lt;/code&gt; &lt;strong&gt;aliases&lt;/strong&gt; your app fetches at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  2. Sending a live call
&lt;/h2&gt;

&lt;p&gt;Both need a real connected model before anything runs — neither offers a free trial&lt;br&gt;
call. With that in place, both Playgrounds render the exact same reply from the exact&lt;br&gt;
same inputs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmwdslykahpzumfzowejh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmwdslykahpzumfzowejh.png" alt="Langfuse Playground with the recreated prompt loaded, showing the real completion in the Output panel" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi3712b5140itrvhlgrvo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi3712b5140itrvhlgrvo.png" alt="Acrux Core Playground's Stored-prompt tab, showing the same completion plus a Gateway Telemetry panel with provider, cost, cache status, and latency" width="800" height="778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Playground&lt;/td&gt;
&lt;td&gt;Runs against any connected model, no telemetry shown inline&lt;/td&gt;
&lt;td&gt;Runs against a &lt;strong&gt;stored prompt reference&lt;/strong&gt;, shows cost/cache/latency inline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requires a real key&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  3. Tracing &amp;amp; observability
&lt;/h2&gt;

&lt;p&gt;Same call, two different trace shapes. Acrux Core's trace is one span, written as a&lt;br&gt;
side effect of the gateway call itself. Langfuse's is a two-level tree — a parent&lt;br&gt;
span wrapping the generation — because its SDK instruments the call rather than&lt;br&gt;
routing it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fii3u7y4paegvxewsjyap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fii3u7y4paegvxewsjyap.png" alt="Langfuse's trace detail: a two-node span tree (request span + generation span), 1.81s latency, $0.000048 cost, 154 total tokens" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fytfydcq76zt8qhc66g6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fytfydcq76zt8qhc66g6k.png" alt="Acrux Core's trace detail: one LLM span with model, provider, tokens, cost, and latency, linked back to the exact gateway request and prompt version" width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Trace shape&lt;/td&gt;
&lt;td&gt;Span tree (request + generation)&lt;/td&gt;
&lt;td&gt;Single span per gateway call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How it's produced&lt;/td&gt;
&lt;td&gt;Client-side OTel instrumentation&lt;/td&gt;
&lt;td&gt;Automatic — a side effect of the gateway call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Links back to prompt version&lt;/td&gt;
&lt;td&gt;Not surfaced in this run&lt;/td&gt;
&lt;td&gt;Yes — "View traces for this prompt version"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  4. The gateway asymmetry
&lt;/h2&gt;

&lt;p&gt;Acrux Core's gateway sits &lt;strong&gt;in the request path&lt;/strong&gt;: every call is routed through it, so&lt;br&gt;
BYOK provider selection, caching, budgets, and virtual keys all apply before the&lt;br&gt;
provider is ever called, and the trace is a side effect of that same hop. Langfuse&lt;br&gt;
isn't a request-path product — it ingests a trace &lt;em&gt;after&lt;/em&gt; your own client made the&lt;br&gt;
call — so there's nothing to route, cache, or budget against on its side. That's a&lt;br&gt;
structural difference in what each product is, not something Langfuse does worse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi3712b5140itrvhlgrvo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi3712b5140itrvhlgrvo.png" alt="Acrux Core's Gateway Telemetry panel — provider, model, cost, cache status, and latency, all computed inline before the response is returned" width="800" height="778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Request-path gateway&lt;/td&gt;
&lt;td&gt;No — call providers yourself, trace is reported after&lt;/td&gt;
&lt;td&gt;Yes — every call routes through it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYOK, caching, budgets, virtual keys&lt;/td&gt;
&lt;td&gt;Not applicable — no request path to apply them to&lt;/td&gt;
&lt;td&gt;Built in, applied before the provider call&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  5. Tool/agent instrumentation
&lt;/h2&gt;

&lt;p&gt;Acrux Core has a real &lt;strong&gt;Tool Catalog&lt;/strong&gt; — callable functions, versioned like prompts,&lt;br&gt;
with their own analytics page. Langfuse has nothing like it: the closest thing is a&lt;br&gt;
"Create new tool" button tucked inside the Playground, which just defines a JSON&lt;br&gt;
Schema for function-calling and saves it project-wide — we made one, reloaded the page&lt;br&gt;
in a fresh window, and it was still there, offered back to us in the same combobox. So&lt;br&gt;
it persists, but that's all it does: no catalog page, no list view outside that one&lt;br&gt;
dropdown, no version history, no analytics, and nothing actually &lt;em&gt;executes&lt;/em&gt; it —&lt;br&gt;
Langfuse hands the schema to the model and stops there. Acrux Core's tools are wired&lt;br&gt;
into the gateway, so a call is a real, traced execution with its own cost and latency,&lt;br&gt;
not just a shape the model is told about.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F511j4tusekbthkofgybx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F511j4tusekbthkofgybx.png" alt="Langfuse's Create LLM Tool dialog in the Playground, defining get_ticket_priority with a JSON Schema parameter" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqme96ppkxs6kjy6roze8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqme96ppkxs6kjy6roze8.png" alt="Langfuse's saved tool re-appearing in the Playground's tool picker after a full page reload, confirming it's stored project-wide, not per-session" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs9bnnlvwcwrb7ywomcgt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs9bnnlvwcwrb7ywomcgt.png" alt="Acrux Core's Tools page listing a dozen real, versioned tools including get_order_status, query_database, and get_weather" width="799" height="571"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsw8kun946a5qww6wdt6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsw8kun946a5qww6wdt6f.png" alt="Acrux Core's Tool analytics page — call volume, error rate, and P50/P95 latency per tool, aggregated from traced executions" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tool catalog&lt;/td&gt;
&lt;td&gt;A schema saved from the Playground, reusable project-wide, but no dedicated page or list view&lt;/td&gt;
&lt;td&gt;Persistent, versioned catalog with its own page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution&lt;/td&gt;
&lt;td&gt;None — the schema is shown to the model, never run&lt;/td&gt;
&lt;td&gt;Real, gateway-executed calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool analytics&lt;/td&gt;
&lt;td&gt;Not available&lt;/td&gt;
&lt;td&gt;Calls, error rate, and latency per tool&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  6. Evaluation &amp;amp; datasets
&lt;/h2&gt;

&lt;p&gt;Both build datasets and run experiments against them, but the on-ramp differs.&lt;br&gt;
Langfuse lets you type a dataset item by hand or pull one from a trace; Acrux Core&lt;br&gt;
builds datasets &lt;strong&gt;only&lt;/strong&gt; from real feedback on a trace — and specifically, only from&lt;br&gt;
&lt;strong&gt;span-level&lt;/strong&gt; feedback, so a single-span trace's own thumbs-up can't be turned into a&lt;br&gt;
dataset (we hit this directly and had to reuse a trace with more than one span).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fojs86y5r9pofvv2ik7t9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fojs86y5r9pofvv2ik7t9.png" alt="Langfuse's Create dataset item dialog, with the flattened input variables and a hand-written expected output" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3gnxojqa3tovi0taseh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3gnxojqa3tovi0taseh7.png" alt="Langfuse's experiment result row: real input/output pairs, but Total Cost showing $0.00 for a custom model without registered pricing" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxnqg7mz5gmcbrcpd4ssm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxnqg7mz5gmcbrcpd4ssm.png" alt="Acrux Core's dataset built from a real feedback row, since the vip-support-triage trace's own single-span feedback wasn't eligible" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2t2um07dq07vwox9n0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2t2um07dq07vwox9n0a.png" alt="Acrux Core's Run report for that dataset against gpt-4o-mini — a plain, unscored manual run" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dataset creation&lt;/td&gt;
&lt;td&gt;Manual entry, API, or from a trace&lt;/td&gt;
&lt;td&gt;From trace feedback only — and only &lt;strong&gt;span-level&lt;/strong&gt; feedback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Experiments&lt;/td&gt;
&lt;td&gt;Prompt × model matrix, evaluator step in the wizard&lt;/td&gt;
&lt;td&gt;Version × model sweep with an automatic baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost accounting we actually saw&lt;/td&gt;
&lt;td&gt;$0.00 for an unregistered custom model&lt;/td&gt;
&lt;td&gt;Real per-call cost, computed inline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  7. SDK &amp;amp; developer experience
&lt;/h2&gt;

&lt;p&gt;Same call, two SDK philosophies. Acrux Core's SDK has dedicated surfaces —&lt;br&gt;
&lt;code&gt;hub.prompts.render()&lt;/code&gt; then &lt;code&gt;hub.gateway.chat()&lt;/code&gt; — and the trace is automatic.&lt;br&gt;
Langfuse wraps a client you already own; the trace only appears once you open an&lt;br&gt;
explicit observation context around the call.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;acx_sdk_run.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;rendered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prompts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vip-support-triage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;production&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VARIABLES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;prompt_version_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;lf_trace_run.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;langfuse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_observation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vip-support-triage-request&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;as_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;span&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai/gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_message&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both produced a real trace within seconds of the call returning:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkhji42j34j2yjrg5s3h1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkhji42j34j2yjrg5s3h1.png" alt="Langfuse's trace for the script-generated call: same VIP reply, 1.81s latency, $0.000048, OpenTelemetry SDK metadata visible" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq6gkku1kezjh0qrqb7r8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq6gkku1kezjh0qrqb7r8.png" alt="Acrux Core's trace for the script-generated call: 144 tokens, $0.0000414, 1.90s latency, linked gateway request" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Full scripts: &lt;a href="https://github.com/AcruxCore/AcruxCore/blob/main/scripts/blogs/acruxcore-vs-langfuse/python/acx_sdk_run.py" rel="noopener noreferrer"&gt;&lt;code&gt;acx_sdk_run.py&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/AcruxCore/AcruxCore/blob/main/scripts/blogs/acruxcore-vs-langfuse/python/lf_trace_run.py" rel="noopener noreferrer"&gt;&lt;code&gt;lf_trace_run.py&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SDK model&lt;/td&gt;
&lt;td&gt;Wrap your own client (&lt;code&gt;langfuse.openai&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Dedicated &lt;code&gt;hub.prompts&lt;/code&gt; / &lt;code&gt;hub.gateway&lt;/code&gt; surface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Getting a trace&lt;/td&gt;
&lt;td&gt;Requires an explicit observation context&lt;/td&gt;
&lt;td&gt;Automatic side effect of &lt;code&gt;hub.gateway.chat()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  8. Latency overhead — measured
&lt;/h2&gt;

&lt;p&gt;We timed the identical call three ways, interleaved in rotating order over 100 rounds&lt;br&gt;
so a network blip hits all three equally: a raw direct call to OpenRouter (baseline),&lt;br&gt;
the same call wrapped in Langfuse's SDK, and the same call through Acrux Core's&lt;br&gt;
gateway. This measures two different kinds of overhead — Langfuse's is client-side&lt;br&gt;
instrumentation cost, Acrux Core's is an extra network hop that buys routing, caching,&lt;br&gt;
and tracing — not a rigged head-to-head.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;p95&lt;/th&gt;
&lt;th&gt;p99&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Direct to provider&lt;/td&gt;
&lt;td&gt;999 ms&lt;/td&gt;
&lt;td&gt;1551 ms&lt;/td&gt;
&lt;td&gt;1940 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Langfuse SDK&lt;/td&gt;
&lt;td&gt;1015 ms&lt;/td&gt;
&lt;td&gt;1775 ms&lt;/td&gt;
&lt;td&gt;2189 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acrux Core gateway&lt;/td&gt;
&lt;td&gt;1243 ms&lt;/td&gt;
&lt;td&gt;2078 ms&lt;/td&gt;
&lt;td&gt;2488 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With a 95% bootstrap confidence interval on the gap against the direct-call baseline:&lt;br&gt;
Langfuse's &lt;strong&gt;+15ms is statistically indistinguishable from zero&lt;/strong&gt; (CI [-90, +150]ms) —&lt;br&gt;
its instrumentation cost doesn't clear the noise floor at this sample size. Acrux&lt;br&gt;
Core's &lt;strong&gt;+260ms is real&lt;/strong&gt; (CI [+157, +360]ms) — the cost of the extra hop, not a&lt;br&gt;
measurement artifact.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Developer experience — what actually surprised us
&lt;/h2&gt;

&lt;p&gt;Real friction hit while doing this comparison, not a symmetric wish list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Langfuse&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👍 Self-hosting was fast — one &lt;code&gt;docker compose up&lt;/code&gt;, working on first login.&lt;/li&gt;
&lt;li&gt;👍 The experiment wizard validates your dataset variables against the prompt &lt;em&gt;before&lt;/em&gt; it spends a call.&lt;/li&gt;
&lt;li&gt;👎 Flat templating pushed the VIP-branch and ticket-list logic back onto the caller (see aspect 1 above).&lt;/li&gt;
&lt;li&gt;👎 The Playground doesn't produce a trace — only a scripted SDK call does.&lt;/li&gt;
&lt;li&gt;👎 A doc example called &lt;code&gt;start_as_current_span&lt;/code&gt;, which doesn't exist on SDK 4.14.1; the real method is &lt;code&gt;start_as_current_observation&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Acrux Core&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👍 Nothing to instrument — &lt;code&gt;hub.gateway.chat()&lt;/code&gt; (or the Playground) writes the trace as a side effect, no wrapper client.&lt;/li&gt;
&lt;li&gt;👍 Nunjucks conditionals and loops are real template logic, not something you flatten by hand first.&lt;/li&gt;
&lt;li&gt;👎 A model with no registered per-1M rate shows a blank &lt;code&gt;—&lt;/code&gt; cost instead of &lt;code&gt;$0&lt;/code&gt; or an estimate, until you register one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time-to-first-trace:&lt;/strong&gt; Acrux Core gets there on the first call with zero&lt;br&gt;
tracing-specific code. Langfuse gets there too, but only through the SDK path, and only&lt;br&gt;
after wrapping a client and opening an observation context.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Open source &amp;amp; self-hosting
&lt;/h2&gt;

&lt;p&gt;Both are open source, under different terms. Acrux Core is &lt;strong&gt;Elastic License 2.0&lt;/strong&gt; —&lt;br&gt;
source-available: read it, modify it, self-host it, but don't resell it as a hosted&lt;br&gt;
service. Langfuse splits its repo: the core is &lt;strong&gt;MIT&lt;/strong&gt;, genuinely permissive, while its&lt;br&gt;
&lt;code&gt;ee/&lt;/code&gt; directories carry a separate Enterprise License gating specific features — which&lt;br&gt;
is exactly why this post's audit-log screenshot (aspect 13) shows a locked door on&lt;br&gt;
self-hosted Langfuse. Both ship a Docker Compose path for local self-hosting; this post&lt;br&gt;
used exactly that for Langfuse.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;MIT core + separate Enterprise License on &lt;code&gt;ee/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Elastic License 2.0 (source-available, not permissive)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-host path&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker compose up&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Postgres + Node stack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  11. Team &amp;amp; org structure
&lt;/h2&gt;

&lt;p&gt;Langfuse has a real two-level hierarchy — organization above project — visible as a&lt;br&gt;
breadcrumb on every settings page. Acrux Core is deliberately flatter: one team, one&lt;br&gt;
member list, no separate layer above it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgd1p63i7p062h5gkiob9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgd1p63i7p062h5gkiob9.png" alt="Langfuse's Project Settings showing the org (AcruxCore) → project (Demo) breadcrumb and hierarchy in the debug metadata" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F16kumgd1svv7ugzhm97i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F16kumgd1svv7ugzhm97i.png" alt="Acrux Core's single Team page — members, invites, and team API keys together, no org layer above" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structure&lt;/td&gt;
&lt;td&gt;Organization → project hierarchy&lt;/td&gt;
&lt;td&gt;Single team-scoped model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best fit&lt;/td&gt;
&lt;td&gt;Many separate workspaces under one org&lt;/td&gt;
&lt;td&gt;One team, one place to look&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  12. Pricing
&lt;/h2&gt;

&lt;p&gt;As of 2026-08-06. Acrux Core is free during beta, bring-your-own provider keys, no&lt;br&gt;
published paid tier yet. Langfuse's hosted cloud (langfuse.com/pricing):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Price/mo&lt;/th&gt;
&lt;th&gt;Included&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hobby&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;50k units/mo, 30-day data access, 2 users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;td&gt;$29&lt;/td&gt;
&lt;td&gt;100k units/mo, 90-day data access, unlimited users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$199&lt;/td&gt;
&lt;td&gt;100k units/mo, 3-year data access, SOC2/ISO27001, HIPAA BAA available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;$2,499&lt;/td&gt;
&lt;td&gt;Audit logs, SCIM API, custom rate limits, dedicated support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice that Langfuse's audit logs — the feature gated in aspect 13 below — are an&lt;br&gt;
&lt;strong&gt;Enterprise-tier&lt;/strong&gt; ($2,499/mo) feature on hosted Langfuse too, not just a self-host&lt;br&gt;
limitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Security, access control &amp;amp; data handling
&lt;/h2&gt;

&lt;p&gt;Only rows for what we actually saw — nothing assumed either way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F10400nx9totfz8py6o4o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F10400nx9totfz8py6o4o.png" alt="Acrux Core's team-wide Capture payloads toggle, on by default" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff9tqv9nobjdxzjvw470y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff9tqv9nobjdxzjvw470y.png" alt="Acrux Core's per-prompt Audit tab with real entries — version commits and alias promotions" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8g1hyi67bha2037s8rgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8g1hyi67bha2037s8rgn.png" alt="Langfuse's Project Members table with a two-tier RBAC model — Organization Role set to Owner, but Project Role reading " width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvzwbwy7hucodfbyukjty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvzwbwy7hucodfbyukjty.png" alt="Langfuse's Audit Logs settings page stating plainly that audit logs are an Enterprise feature" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RBAC&lt;/td&gt;
&lt;td&gt;Two-tiered (org role + project role) by design, but &lt;strong&gt;Project Role reads "N/A on plan"&lt;/strong&gt; on this account&lt;/td&gt;
&lt;td&gt;Single role per team member, no org-level layer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit log&lt;/td&gt;
&lt;td&gt;Present in the UI, &lt;strong&gt;gated behind the Enterprise plan&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Present and populated by default, no upgrade needed — but scoped to one prompt at a time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payload/data capture control&lt;/td&gt;
&lt;td&gt;Not found in any settings page checked&lt;/td&gt;
&lt;td&gt;Team-wide &lt;code&gt;Capture payloads&lt;/code&gt; toggle, on by default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Neither story is simply "better": Langfuse's model is broader by design — org/project&lt;br&gt;
RBAC, a team-wide audit log — but a real chunk of it sits behind a paid plan even for a&lt;br&gt;
self-hosted admin. Acrux Core's audit trail is free and on by default, but narrower —&lt;br&gt;
one prompt at a time, not the whole team.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Community &amp;amp; maturity
&lt;/h2&gt;

&lt;p&gt;A footnote, not a scored comparison. Retrieved live from each project's own GitHub&lt;br&gt;
page, 2026-08-06:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stars&lt;/td&gt;
&lt;td&gt;32,617&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Latest release&lt;/td&gt;
&lt;td&gt;v4.5.0&lt;/td&gt;
&lt;td&gt;none tagged yet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repo age&lt;/td&gt;
&lt;td&gt;Multi-year, active&lt;/td&gt;
&lt;td&gt;Opened 2026-08-03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contributors&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;Not yet computed by GitHub&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Langfuse is a mature, widely-used project. Acrux Core's public mirror is three days&lt;br&gt;
old. Both facts matter to someone deciding what to depend on.&lt;/p&gt;

&lt;h2&gt;
  
  
  15. Verdict
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Langfuse&lt;/th&gt;
&lt;th&gt;Acrux Core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Strongest at&lt;/td&gt;
&lt;td&gt;Tracing depth, org/project structure, eval tooling maturity&lt;/td&gt;
&lt;td&gt;A request-path gateway with routing, caching, and budgets on every call; tools that actually execute and get measured, not just described; datasets built straight from real production feedback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weakest at&lt;/td&gt;
&lt;td&gt;No request-path gateway; tools are a schema in a Playground dropdown, not a catalog; RBAC and audit gated behind paid tiers&lt;/td&gt;
&lt;td&gt;Narrower eval ecosystem and community maturity; audit scoped per-prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pick it if&lt;/td&gt;
&lt;td&gt;You want mature, OTel-native observability layered onto a client you already own&lt;/td&gt;
&lt;td&gt;You want the provider call itself — gateway, tools, feedback-driven datasets — traced for free, with nothing bolted on after the fact&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Tracing depth and eval-tooling maturity are real Langfuse wins — aspect 3 above&lt;br&gt;
and its years of usage show that. But on the three things that make up the actual&lt;br&gt;
day-to-day loop of running an LLM app — the gateway, the tool catalog, and building&lt;br&gt;
datasets from feedback — this comparison came down in Acrux Core's favor every time,&lt;br&gt;
not just "different shape." Langfuse has no request-path gateway at all&lt;br&gt;
(aspect 4), its "tool" is a schema saved from a Playground&lt;br&gt;
dropdown that's never actually executed (aspect 5), and&lt;br&gt;
its datasets are built by hand or pulled from a trace, not generated from feedback&lt;br&gt;
your users already gave (aspect 6). Acrux Core does all&lt;br&gt;
three natively, in one integrated flow.&lt;/p&gt;

&lt;p&gt;Want to run this yourself? The &lt;a href="https://docs.acruxcore.com/docs/getting-started/quickstart" rel="noopener noreferrer"&gt;Quickstart&lt;/a&gt; gets you&lt;br&gt;
from sign-up to a traced, gateway-routed call in about ten minutes.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>observability</category>
    </item>
  </channel>
</rss>
