Skip to main content

AcruxCore vs Langfuse vs LangSmith: one app tested end to end on all three

· 15 min read
LLM-ops platform

This post compares AcruxCore, Langfuse and LangSmith on the things a developer checks before choosing one. We also ran one app on all three platforms, with the same code, data, prompts and model, and measured each step. The app is a small agent that reads a client's email, checks each request against a signed project scope, prices the extra work, and writes a reply.

Differences at a glance​

AcruxCoreLangfuseLangSmith
LicenseApache 2.0, every featureMIT core; some features under a commercial licenseSDKs MIT; the platform is not open source
Self-hostingFree, every featureFree core; roles, audit log and retention policies need a licenseEnterprise plan only
Hosted price, 100,000 traces a month, 3 people$0 during the beta; later price not set$98.36 on the Core plan$567 on the Plus plan
Hosted free planThe whole beta; no trace or seat limit on the pricing page50,000 units a month, 2 users (a unit is a trace, a step or a score)5,000 traces a month, 1 seat
Data kept on that hosted planMessage content 90 days; tokens, cost and timing are not deleted90 days14 days; 180 days costs extra
Hosted regionsNot stated; no choiceUS, EU, JapanUS, EU, Asia-Pacific
SDK languagesPython, TypeScriptPython, TypeScriptPython, TypeScript, Go, Java
OpenTelemetry ingestYesYesYes
OpenAI Agents SDK, LangChain and CrewAI integrationsYesYesYes
Vercel AI SDK integrationNoYesYes
Gateway in the request pathYes: fallbacks, cache, budgets, rate limitsNoYes, in beta: routing, spend and rate limits
Evaluations: datasets, LLM judge, your own code, live trafficYesYesYes
Review queue for peopleNoYesYes
AlertsEmail: budgets, evaluation rules, weekly digestCost, latency, scores; Slack, webhookCost, errors, latency, feedback; Slack, PagerDuty, webhook
SSONoPro with the Teams add-on, or EnterpriseEnterprise
Audit logEvery plan, also self-hostedEnterpriseEnterprise
GitHub stars, 17 October 20261135,935No public platform repository

Sources: the Langfuse license, pricing, self-hosting and alerts pages; the LangSmith pricing, self-hosting, regions, gateway and alerts pages; and acruxcore.com/pricing. The prices were read on 16 October 2026, and everything else on 17 October 2026.

AcruxCore​

Pros

  • The hosted service is free during the beta, with no trace or seat limit.
  • Every feature is open source under Apache 2.0, and self-hosting is free, with no paid features.
  • The gateway sits in the request path. It has fallbacks, a cache, budgets, rate limits and virtual keys (keys you give an app in place of your provider key). It traces every call with no wrapper in your code. Our test did not use it, to match the other two legs.
  • The audit log, which records who changed what, is on every plan, hosted or self-hosted.
  • The comparison of two experiment runs opens on the test messages whose score changed.
  • Prompts use Jinja2-style templates with if and for, and the server can fill them in.
  • It has a versioned tool catalog that the gateway runs, and a built-in prompt optimizer.

Cons

  • It has no review queue. In our test, reviewing one reply by hand took 4 clicks, and 2 on Langfuse and LangSmith.
  • The Traces list shows each trace's name, not the user's message, so finding one message means opening rows.
  • The SDK has no experiment runner. Your code loops over the test messages and stores the results with 3 REST calls.
  • It has no SSO, and the hosted service does not state its data region.
  • No price is published for after the beta.
  • The community is small: 11 GitHub stars.
  • Alerts arrive by email only, and there is no Vercel AI SDK integration.
  • The SDK has no wrapped OpenAI client, so the test app needed 4 more lines than on Langfuse.
  • A model call links to its prompt version but does not print the prompt's name or version number.

Langfuse​

Pros

  • Our app needed the fewest lines of tracing code: 11.
  • It has a review queue: 2 clicks per reply.
  • The core is MIT-licensed and free to self-host.
  • It has the largest community of the three: 35,935 GitHub stars.
  • For 100,000 traces a month and 3 people, it costs $98.36 a month and keeps data for 90 days.
  • A model call shows its prompt name and version as a link.

Cons

  • It has no gateway.
  • Its comparison of two experiment runs cannot hide the test messages whose score stayed the same.
  • It bills each step and each score, so the bill grows with the number of steps in a trace.
  • SSO and project roles need the paid Teams add-on, and the audit log needs Enterprise.
  • A promotion asks for no confirmation, and the prompt page does not show past promotions.
  • An experiment with a plain Python function runs one test message at a time.

LangSmith​

Pros

  • It is the only one of the three with both a review queue and a filter for the test messages whose score changed. AcruxCore has the filter but no queue. Langfuse has the queue but no filter.
  • It has SDKs for Go and Java as well as Python and TypeScript.
  • It has a gateway, in beta.
  • The prompt page keeps a rollback history.
  • Alerts reach Slack, PagerDuty and webhooks.

Cons

  • For 100,000 traces a month and 3 people, it costs $567 a month, more than five times the Langfuse price, and keeps data for 14 days.
  • The platform is not open source, and self-hosting needs the Enterprise plan.
  • Pushing a prompt from code needs the langchain-core package.
  • A prompt read with no tag returns the newest commit, not the production one, so a draft can reach users. Langfuse returns the production version.
  • The SDK caches a prompt for 5 minutes, so a promotion takes up to 5 minutes to arrive.

Which one to choose​

  • AcruxCore if you want a free hosted service or a free self-host with every feature, including a gateway and an audit log, and you can work without a review queue or SSO.
  • Langfuse if you want an open-source platform with a large community, a review queue and a low, known price.
  • LangSmith if you want a review queue and the filter for changed scores in one product, or need Go or Java, and $567 a month fits your budget.

How we tested​

  • The app: a small agent in four steps (extract, classify, price, reply), in one file, pipeline.py, with no tracing code in it. More about the app.
  • The data: 30 client messages with the expected items and total, three scorers, and two versions of the prompts. All three platforms got the same files.
  • The model: every call, the judge included, went to z.ai glm-5.3 with reasoning_effort="low", straight from the app.
  • The platforms: Langfuse and LangSmith on their hosted EU regions, on the free plans. AcruxCore on its hosted service at acruxcore.com.
  • The AcruxCore leg: a clean environment with Python 3.12, acruxcore 0.18.0, openai 2.48.0, httpx and python-dotenv.

Tracing​

AcruxCoreLangfuseLangSmith
Lines of tracing code for this app151118
Wrapped OpenAI clientNoYesYes
Decorator that makes a function a stepYesYesYes
Model call shows its prompt versionA link, "View traces for this prompt version"; no name or number"prompt: scope-extract - v1", as a linkPlain metadata text, not a link
Gateway that records calls with no wrapperYesNoYes, in beta

These are all 15 lines of the AcruxCore instrumentation:

from types import SimpleNamespace
from acruxcore import AcruxCoreSync

hub = AcruxCoreSync(ACX_KEY, ACX_BASE_URL, timeout=180,
provider={"base_url": BASE_URL, "api_key": API_KEY})

def _create(*, model, messages, acx_prompt_version=None, **params): # a z.ai call, traced
result = hub.gateway.chat(model, messages, prompt_version_id=acx_prompt_version, **params)
return SimpleNamespace(choices=[SimpleNamespace(message=SimpleNamespace(content=result.content))])

client = SimpleNamespace(chat=SimpleNamespace(completions=SimpleNamespace(create=_create)))

def step(name: str, kind: str):
return hub.traces.step(name, kind=kind)

def make_app(alias: str = "production", only: set[str] | None = None):
def get_prompt(name: str): # `only` limits `alias` to some prompts; the rest stay on production
version = hub.prompts.get_by_alias(name, alias if not only or name in only else "production")
return version.messages, {"acx_prompt_version": version.id}
return build_app(get_prompt, client, step)
  • ACX_KEY, ACX_BASE_URL, BASE_URL and API_KEY come from environment variables. build_app is the shared app in pipeline.py, the same for all three platforms.
  • AcruxCoreSync is the SDK's blocking client, for code that is not async.
  • The provider setting gives the SDK our z.ai URL and key, so each model call goes straight to z.ai, as on the other two platforms.
  • traces.step is the decorator. Each step becomes a span, and each model call becomes a span under its step.
  • _create and the client line are the 4 lines that Langfuse does not need. The AcruxCore SDK has no wrapped OpenAI client, so these lines give the SDK's chat call the OpenAI shape that the app expects.
  • The full file is acruxcore_sdk_leg.py.

All three platforms stored the same tree: the agent, scope-check, at the root, one span per step, one model call inside each step, and the price step marked as a tool.

AcruxCore trace for one message: scope-check at the root, with extract, classify once for each of the two requests, a price tool and reply, each step holding a glm-5.3 LLM span, and 2,132 tokens and $0.00285 in the header

AcruxCore LLM span panel showing model glm-5.3, provider api.z.ai, 791 tokens of which 704 cached prompt tokens, cost $0.000461, latency 1.93 s, and the links View traces for this prompt version and Open in Playground

The AcruxCore gateway is an OpenAI-compatible endpoint in the request path:

  • You point the OpenAI client at AcruxCore, and each call arrives as a priced span. Your code needs no wrapper.
  • The gateway passes reasoning_effort on to the model, so a call through the gateway runs the model with the same settings. One extract call used 3 reasoning tokens with "low" and 149 without it.
  • We did not use the gateway for this test. The other two legs called z.ai directly, and the extra network hop would have added to AcruxCore's latency only.

Prompts, promotion and rollback​

AcruxCoreLangfuseLangSmith
How a chat prompt is storedA list of role and content messagesA list of role and content messagesA serialized LangChain object
Push a prompt from codePython SDK or RESTPython SDKNeeds the langchain-core package
Promote a version4 clicks, with a confirmation3 clicks, no confirmation3 clicks, with a confirmation
Roll back2 clicks on the same tab4 clicks3 clicks
History of promotionsAudit tab: who moved the alias, and whenNot shownRollback list of past commits
SDK cache before a promotion reaches the app60 seconds60 seconds5 minutes
  • AcruxCore listed each prompt's variables from its {{ }} placeholders.
  • AcruxCore created a production and a staging alias on version 1 of each prompt. Committing version 2 did not move them.
  • hub.prompts.get_by_alias(name, alias) returns the version that the alias points to. AcruxCore can also fill in the variables on the server and return the finished messages.

AcruxCore Audit tab for scope-extract: production moved v1 → v2, then v2 → v1, each with who made the change and when

Experiments over the dataset​

An experiment answers one question: after you change a prompt, which messages got better and which got worse? We tested it like this:

  • The dataset is 30 client messages for a fictional yoga-studio website, in messages.json. Each message has the expected answer: the extra-work items and the total price.
  • Three scorers check each answer: are the items exactly right, is the total exactly right, and does an LLM judge accept the reply.
  • v1 is the first version of the prompts. v2 is a rewrite of the extract and classify prompts, made after reading v1's mistakes.
  • On each platform, we ran the app over the 30 messages once with v1 and once with v2, and then opened the platform's comparison of the two runs.

On AcruxCore, v2 fixed 2 messages and broke 2 others. The comparison has to show those 4 messages. The table shows how each platform handled that.

AcruxCoreLangfuseLangSmith
Upload the 30 test messages1 call, 1.0 s30 calls, 7.3 s1 call, 2.2 s
Run your own app code as an experimentYes, a local run: your code runs the app, and 3 REST calls store the resultsYes, run_experimentYes, evaluate
Experiment runner in the SDKNo; your code loops over the test messagesYes; a plain function runs one message at a timeYes; a plain function runs 4 at a time
Clicks to the comparison of two runs3, from the Evaluations page4, from the dataset page4, from the dataset page
See only the messages whose score changedYes, the comparison opens that wayNo; scan all 30 rowsYes, one click
  • We do not compare the scores across platforms. All three ran the same prompts on the same model, and glm-5.3 gives a slightly different answer each time, so score gaps between platforms are noise. The scores of every run are in the run log.
  • AcruxCore also has a server-side experiment, which runs one stored prompt over a dataset with an LLM judge. That kind cannot run this app, because the app has four steps and two of its scorers are Python code.

AcruxCore Compare per example: base v1, target v2, Changed 4 selected, two messages improved and two regressed on the items score

Reviewing replies by hand​

We asked one question about each of the 30 replies: "Would you send this reply to the client as is?"

AcruxCoreLangfuseLangSmith
Review queueNoYesYes
Clicks per reply4: open the trace, open the reply step, ▲ or ▼, go back2: a verdict and "Mark Completed"2: a verdict and "Next"
The verdict names the questionNo; a ▲/▼ rating on the stepYes, a score configurationYes, a feedback key
Fix a wrong answerA comment and a label on the trace"Correct output" saves your text"Add to Dataset" adds your edited version to the dataset
  • AcruxCore's Traces list shows each trace's name, not the client's message, so finding one message means opening rows.
  • We would send 28 of the 30 AcruxCore v1 replies unchanged.

Live traffic​

We sent the 30 messages to all three platforms during the same 5 minutes, one at a time, and read the numbers back through each platform's API.

AcruxCoreLangfuseLangSmith
Latency p50 / p957.7 s / 10.6 s7.2 s / 10.8 s7.6 s / 11.2 s
Model cost per trace, paid to z.ai$0.0016$0.0015$0.0017
Dashboards with no setupYesYesYes
  • The latency is almost all model time, because all three called the same z.ai endpoint.
  • We sent this traffic on 16 October 2026, 17:18–17:22 UTC. The model's speed changes during the day. At 06:03 UTC the same app had a p50 of about 16.9 s on Langfuse and LangSmith (Langfuse vs LangSmith), so compare the columns with each other, not with latencies from another hour.
  • The model cost is z.ai's bill for one message, not a platform fee. It differs because the model wrote replies of different lengths.
  • On all three platforms, we entered z.ai's prices for glm-5.3: $1.40 per million input tokens, $0.26 per million cached input tokens, and $4.40 per million output tokens.
  • On AcruxCore, 85% of the input tokens were cached. At the full input price, the 30 traces would have cost $0.088 instead of $0.048.
  • AcruxCore's Dashboards page splits requests, errors, tokens, cost and latency by day, model, session, prompt version or step.

AcruxCore Traces page for the live run: each scope-check row shows its spans, tokens, cost and duration

Price for 100,000 traces a month​

Plan3 peopleData kept
AcruxCore Beta (hosted)$0; no price published for after the betaMessage content 90 days; tokens, cost and timing are not deleted
Langfuse Core$98.36, or $119.69 when each trace also gets three scores90 days
LangSmith Plus$56714 days; 180 days costs extra

Run it yourself​