Compare
Dwarf vs. Temporal vs. LangGraph
Temporal made durable execution mainstream, and LangGraph made agent graphs easy to write. Both are excellent projects. Dwarf takes a different position: durable agentic workflows as a library in your own application, with your database as the only infrastructure. Here is what that trade looks like, with sources for every claim we make about the others.
| Dwarf | Temporal | LangGraph | |
|---|---|---|---|
| What it is | A Go library that you embed in your own binary. | A server cluster that you host, or Temporal Cloud, plus an SDK that runs in your workers. | A Python or JavaScript library, plus LangSmith Deployment for managed hosting. |
| Infrastructure you run | Your application and a SQL database. | The Temporal Service (frontend, history, matching and worker services) and its persistence store, or a Temporal Cloud subscription. | Your application and a checkpointer database, or a LangSmith Deployment. |
| Scale-out architecture | Fully distributed. Replicas and database shards coordinate only through the databases. Each step is dispatched on its own, so one flow's parallel branches run at once, split between the two replicas that dispatch its shard. Shards are added with rolling restarts and no maintenance window. | Horizontally scaled services over a sharded history. The history shard count is fixed when the cluster is created, and changing it means migrating to a new cluster. | The library runs each graph in the calling process. To spread runs across machines, the Agent Server adds queue workers over Postgres and Redis, and needs a license key when self-hosted. Each run executes on a single worker, so a run's parallel branches share that worker. |
| What caps throughput | Your databases. A 32-vCPU Postgres runs about 19,000 to 24,000 steps/s, and four such shards ran 3.8× one. Past 32 vCPUs, the database’s write-ahead log is the limit, so you add shards. The methodology is published. | On Cloud, a per-namespace limit of 500 actions/s by default, raised with usage or provisioned capacity. Self-hosted, your cluster and its persistence store. | A single Postgres database holds all durable state, with no sharding documented. Concurrency is the worker count times the runs each worker handles (10 by default). |
| Concurrent long-running tasks | Each task in flight is handled by a worker goroutine, and the engine grows workers on demand, into the tens of thousands per process. A waiting task holds no database connection: one is used only to claim the step and record its outcome. Memory is the practical limit when flow state is large. A measured run held 10,000 one-minute tasks in flight in one process, on under one core. | Activities run in slots on worker processes, 1,000 per worker by default (Go SDK). You add worker processes for more. A single workflow execution can have at most 2,000 incomplete activities on Cloud. | Runs execute on queue workers, 10 concurrent runs per worker by default. A run holds its slot until it finishes or interrupts, including while it waits on LLM and tool calls. You add workers for more. |
| How orchestration logic is written | A declarative graph of transitions, conditions, fan-out and loops, plus tasks that are plain functions, in Go or any other language. Nothing is replayed, so neither layer has determinism constraints. | Imperative workflow code that must be deterministic: it can't read the wall clock, use randomness, iterate maps in their native order, start native goroutines or do I/O. Activities are unrestricted. | A graph of nodes and edges. Node code is unrestricted. |
| Changing code with flows in flight | Each flow keeps the graph it started with. Task code can change mid-flow as long as it still accepts the state already in flight. Retired task names must stay routable until their flows drain. | Any change that alters the command sequence of running workflow code needs a version guard (patching) or worker versioning. | Saved checkpoints resume against the current graph code, so keeping them compatible is up to you. |
| Crash recovery | Automatic. When a lease expires, the step is re-dispatched on another replica. | Automatic, by replaying the event history. | With the library alone, a run resumes from its last checkpoint when the thread is invoked again. On the Agent Server, a sweeper re-queues runs from crashed workers every 2 minutes. |
| State size | Up to 256 MB per value, about what a Postgres jsonb column holds. 250 MB per step was measured. | Cloud allows 2 MB per payload, 4 MB per transaction, and 50 MB or 51,200 events of history per execution. Self-hosted uses the same defaults, but they are configurable. | State is bounded by your checkpointer's database. |
| Human-in-the-loop | Interrupt and Resume | Signals and Updates | interrupt() and a resume command |
| Parallel fan-out and merge | Static and forEach fan-out, with per-field reducers merging results at fan-in. | Child workflows or asynchronous activities. Merging the results is up to your code. | The Send API, with state reducers merging results. |
| Priority and fairness | Priority bands, plus weighted fairness keys within a band. | Task queue priority and fairness keys. | Not built in. |
| Metrics and tracing | OpenTelemetry logs, over 30 metrics and traces, sent to the stack you already run at no cost. | Prometheus metrics, OpenTelemetry tracing and a Web UI. | Tracing through LangSmith ($39 per seat per month on Plus, with 10k traces included and $5 per 1k after that), or through third-party tools. |
| Languages for your code | The host is Go. Graphs and flows are JSON on the wire, so tasks can be written in any language, though there are no task SDKs outside Go yet. | Native SDKs for Go, Java, TypeScript, Python, .NET, PHP, Ruby and Rust. The server itself is written in Go. | Python and JavaScript / TypeScript. |
| License | Apache 2.0 | MIT | MIT |
| Pricing | Free. You pay only your own cloud bill, which comes to about $0.05 per million steps at scale. | Self-hosted, the software is free, but you run and pay for four services, usually replicated, plus their database. Cloud starts at $50 per million actions and drops to $25 with volume. | The library is free. LangSmith Deployment is metered by the resources each deployment consumes, such as $0.0675 per vCPU-hour of runtime compute, and Plus includes one small serverless deployment. |
Good to know
Common questions
- Do my tasks have to be written in Go?
- No. Only the host that embeds the engine is Go, and it implements two callbacks: one loads a graph, the other runs a task. Both can reach any language, over HTTP or any other transport. Graphs and the flow handed to a task are plain JSON, including state and control signals such as retry, sleep and interrupt. There are no ready-made task SDKs for other languages yet, so a non-Go task reads and writes that JSON directly. Microbus runs its workflows on Dwarf this way, with every task behind a URL.
- Who runs the database?
- Whoever runs your databases today. Amazon RDS, Google Cloud SQL and Azure Database for PostgreSQL
all work, and retention is built in: closed flows move to an archive that keeps each day for 30 days by
default (
SetRetention), andPurgeorDeleteOnCompletionremoves flows sooner. There is no separate orchestration service to host, monitor or buy support for: Dwarf runs inside your application, so its availability is your application's and your database's, which you already run to your own standard. - Can I bring my LangGraph graphs?
- The programming models are close: nodes and edges, conditional routing, state reducers, interrupts, and
Sendalongside Dwarf'sforEach. Porting a graph is mostly a mechanical translation, the kind of job a coding agent does well. Node code can keep running in Python behind an HTTP call, LangChain integrations included, while Dwarf takes over durability. - Isn't a graph less expressive than workflow code?
- It is more structured, on purpose. Graphs cover loops, conditional and first-match routing, static and
dynamic fan-out, subgraphs and human-in-the-loop interrupts. Anything a graph can't express goes in a task,
which is plain code, and a task can choose the next step itself with
Goto. In exchange, the graph is data: you can inspect it, draw it and freeze it per flow, and nothing about it is replayed. - Is execution exactly-once?
- In normal operation, each task runs once and its step records exactly one outcome. A task runs a second
time only after a failure: a worker crashes mid-task and its lease expires, the database connection is lost
for longer than the retry budget, or the task overruns its time budget. That makes execution at-least-once,
as with every durable execution engine, and that rare second run is what
StepKey()is for: a stable key per step that makes side effects such as charges and emails idempotent. - What happens when Postgres goes down?
- Work pauses and resumes on its own. In-flight writes wait out a brief freeze; after a severed connection, outcomes are retried when the database returns, and steps whose leases lapsed are re-run. The engine is built not to fail a flow because the database was away, and replicas recover without a restart.
Sources
- Temporal Cloud system limits: payload, transaction, history and per-namespace throughput limits
- Temporal pricing: price per million actions
- Temporal Go workflow basics: workflow determinism constraints
- Temporal SDKs: the supported SDK languages
- Temporal Server: the four services that make up a self-hosted deployment
- Temporal history service architecture: history shards are fixed at cluster creation
- Temporal worker tuning reference: default activity slots per worker
- Agent Server environment variables:
N_JOBS_PER_WORKER, concurrent runs per worker - LangSmith Agent Server scalability: one run per worker, Postgres for all durable state, Redis ephemeral only
- Configure Agent Server for scale: Postgres as the store for all data, sizing guidance
- LangSmith Agent Server data plane: Postgres, Redis, queue workers and self-hosted licensing
- Temporal task queue priority and fairness
- LangGraph persistence: checkpointers and resuming threads
- LangSmith pricing: seats, traces and deployment resource rates
- Google Cloud SQL pricing and Compute Engine pricing: the Dwarf cost model
- Dwarf cloud benchmarks: every Dwarf number on this page
Checked November 2026. Spotted something out of date? Open an issue and we will fix it.