<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://quantumbpm.com/blog</id>
    <title>QuantumBPM Blog</title>
    <updated>2026-05-05T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://quantumbpm.com/blog"/>
    <subtitle>QuantumBPM Blog</subtitle>
    <icon>https://quantumbpm.com/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[BPMN vs. Airflow / Prefect / Dagster: Process or DAG?]]></title>
        <id>https://quantumbpm.com/blog/bpmn-vs-airflow-prefect</id>
        <link href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect"/>
        <updated>2026-05-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical comparison of BPMN engines and DAG-based data orchestrators (Airflow, Prefect, Dagster) — what each is built for and which one you actually need.]]></summary>
        <content type="html"><![CDATA[<p>A question that comes up surprisingly often: "we're picking a workflow tool — should we use Airflow, Prefect, or a BPMN engine?" The fact that it's even a question is interesting, because the three tools are genuinely solving different problems. The confusion comes from the shared word "workflow", which has been overloaded into uselessness.</p>
<p>Short answer: <strong>Airflow, Prefect, and Dagster are DAG-based data orchestrators. BPMN engines are business-process engines. They look similar from far away and feel completely different up close.</strong> This post is about the difference and how to pick.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-shape-of-the-problem-matters">The shape of the problem matters<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#the-shape-of-the-problem-matters" class="hash-link" aria-label="Direct link to The shape of the problem matters" title="Direct link to The shape of the problem matters" translate="no">​</a></h2>
<p>The cleanest way to tell these tools apart is to look at the <em>shape</em> of what each one models.</p>
<p>A <strong>DAG-based orchestrator</strong> like <a href="https://airflow.apache.org/" target="_blank" rel="noopener noreferrer" class="">Airflow</a>, <a href="https://www.prefect.io/" target="_blank" rel="noopener noreferrer" class="">Prefect</a>, or <a href="https://dagster.io/" target="_blank" rel="noopener noreferrer" class="">Dagster</a> models a directed acyclic graph of tasks, run on a schedule (or in response to a trigger). The classic example: an ETL pipeline. "At 02:00 every day, extract from these sources, transform, load into the warehouse, run dbt, send a Slack notification." Each task is a unit of code. The DAG is the dependency graph between them. The scheduler runs the right tasks in the right order at the right time.</p>
<p>A <strong>BPMN engine</strong> models a business process. The classic example: an order fulfilment flow. "When an order arrives, evaluate it. If it's flagged for review, send it to a human. Charge the customer. If charging fails three times, escalate. Ship it." Each step is a typed BPMN element. The diagram is the spec. The engine runs <em>one instance per real-world event</em> (per order, per claim, per onboarding).</p>
<p>The differences cascade from there.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="five-concrete-differences">Five concrete differences<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#five-concrete-differences" class="hash-link" aria-label="Direct link to Five concrete differences" title="Direct link to Five concrete differences" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-cadence">1. Cadence<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#1-cadence" class="hash-link" aria-label="Direct link to 1. Cadence" title="Direct link to 1. Cadence" translate="no">​</a></h3>
<p>DAG orchestrators are <strong>schedule-shaped</strong>. The first-class concept is "this DAG runs every day at 02:00", and most of the platform is built around that — backfills, catchup runs, freshness SLAs, schedule overlap handling.</p>
<p>BPMN engines are <strong>event-shaped</strong>. The first-class concept is "an instance starts when an order arrives". Schedules exist (timer start events) but they're not the centre of gravity. Most instances are triggered by external messages, signals, or API calls.</p>
<p>If your problem is "do this batch on a schedule", DAG. If your problem is "react to this event with a multi-step flow", BPMN.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-instance-lifetime">2. Instance lifetime<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#2-instance-lifetime" class="hash-link" aria-label="Direct link to 2. Instance lifetime" title="Direct link to 2. Instance lifetime" translate="no">​</a></h3>
<p>A DAG run typically lives for the length of a single execution — minutes to hours. When it finishes, it's done. You query its history for debugging.</p>
<p>A BPMN instance routinely lives for <strong>days to weeks</strong>, because business processes do. An onboarding flow might spend two business days waiting for a document. A claims flow might spend a month in adjudication. Long-lived stateful instances with a current position, accumulated variables, and active timers are the <em>normal</em> mode of operation, not the exception.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-humans-in-the-loop">3. Humans in the loop<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#3-humans-in-the-loop" class="hash-link" aria-label="Direct link to 3. Humans in the loop" title="Direct link to 3. Humans in the loop" translate="no">​</a></h3>
<p>DAG orchestrators don't really model humans. You can fake a human approval with a sensor task that polls a database for a flag — and people do — but it's an awkward fit.</p>
<p>BPMN has <strong>user tasks</strong> as a first-class element. The engine holds a token until a person claims and completes the task. Assignment, reassignment, and escalation are all spec-defined. The task list integrates into your own UI via API. Half of business processes have a human step somewhere. That's why BPMN was designed around it.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-error-and-compensation-semantics">4. Error and compensation semantics<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#4-error-and-compensation-semantics" class="hash-link" aria-label="Direct link to 4. Error and compensation semantics" title="Direct link to 4. Error and compensation semantics" translate="no">​</a></h3>
<p>DAG orchestrators model failure as <strong>task retry plus on-failure callbacks</strong>. That covers most data-pipeline cases: a task failed, retry it, or alert if retries exhausted.</p>
<p>BPMN models failure as a layered set of concepts:</p>
<ul>
<li class=""><strong>Errors</strong> with named types, caught at boundary events or in event sub-processes, traversing scope hierarchies (an error inside a sub-process bubbles up until it's caught).</li>
<li class=""><strong>Escalations</strong> that, unlike errors, can be non-interrupting — work continues while someone is alerted.</li>
<li class=""><strong>Compensation</strong> — the formal mechanism for undoing work that already succeeded when something later in the process fails. You don't "retry" a charge that already settled. You compensate it with a refund.</li>
</ul>
<p>If your domain has the shape "we sometimes have to undo earlier work because something later went wrong", you want compensation, and BPMN is the spec that defines it.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-who-owns-the-diagram">5. Who owns the diagram<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#5-who-owns-the-diagram" class="hash-link" aria-label="Direct link to 5. Who owns the diagram" title="Direct link to 5. Who owns the diagram" translate="no">​</a></h3>
<p>A DAG is <strong>owned by engineers</strong>. It's Python (in Airflow, Prefect, Dagster), reviewed as code, and changed via PR.</p>
<p>A BPMN process is owned by the <strong>business</strong>. The diagram is the contract between engineering and the people who actually own the work — product, ops, compliance. It's reviewed by them, signed off by them, and audited by them. The XML serialisation is for the engine. The visual diagram is for the conversation.</p>
<p>This is the deepest difference, and it's the one that determines whether BPMN or a DAG orchestrator is right: <strong>who needs to read, change, and sign off this thing?</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-a-dag-orchestrator-is-the-right-answer">When a DAG orchestrator is the right answer<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#when-a-dag-orchestrator-is-the-right-answer" class="hash-link" aria-label="Direct link to When a DAG orchestrator is the right answer" title="Direct link to When a DAG orchestrator is the right answer" translate="no">​</a></h2>
<p>Use Airflow, Prefect, or Dagster when:</p>
<ul>
<li class="">The work is <strong>data-shaped</strong> — ETL, ingestion, dbt orchestration, ML training pipelines, reporting jobs.</li>
<li class="">The cadence is <strong>scheduled</strong> or pipeline-triggered, not driven by external business events.</li>
<li class="">The audience is <strong>engineers</strong> — data engineers, ML engineers, analytics engineers — not the business.</li>
<li class="">Per-run lifetime is <strong>bounded and short</strong> (minutes to hours).</li>
<li class="">The state model that matters is <strong>dataset freshness and lineage</strong>, not "where is this individual order in its lifecycle".</li>
</ul>
<p>For these cases a BPMN engine is the wrong shape. Don't use one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-a-bpmn-engine-is-the-right-answer">When a BPMN engine is the right answer<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#when-a-bpmn-engine-is-the-right-answer" class="hash-link" aria-label="Direct link to When a BPMN engine is the right answer" title="Direct link to When a BPMN engine is the right answer" translate="no">​</a></h2>
<p>Use a BPMN engine when:</p>
<ul>
<li class="">The work is <strong>business-process-shaped</strong> — onboarding, claims, approvals, fulfilment, KYC, case management, underwriting.</li>
<li class="">Each instance corresponds to a <strong>real-world event</strong> (an order, a claim, a customer) and lives for as long as that event takes to resolve.</li>
<li class=""><strong>Humans are part of the flow</strong> — claiming, approving, completing tasks.</li>
<li class=""><strong>Audit, compliance, and governance</strong> are non-negotiable requirements, not nice-to-haves.</li>
<li class="">The diagram <strong>needs to be readable by non-engineers</strong>, who will review and sign off changes.</li>
</ul>
<p>These are not data-pipeline characteristics. They're business-process characteristics. Different shape, different tool.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-boring-answer-most-large-orgs-need-both">The boring answer: most large orgs need both<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#the-boring-answer-most-large-orgs-need-both" class="hash-link" aria-label="Direct link to The boring answer: most large orgs need both" title="Direct link to The boring answer: most large orgs need both" translate="no">​</a></h2>
<p>A retailer running data pipelines for analytics <em>and</em> an order-fulfilment process for live transactions needs <strong>both</strong> — Airflow for the warehouse jobs, a BPMN engine for the order flow. They don't compete. They don't even sit in the same plane.</p>
<p>The mistake is forcing one shape into the other:</p>
<ul>
<li class="">A DAG of "wait for human approval" tasks is a bad BPMN process.</li>
<li class="">A BPMN process of "extract, transform, load" steps is a bad data pipeline.</li>
</ul>
<p>Match the tool to the shape and the rest is straightforward.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-quantumbpm-fits">How QuantumBPM fits<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#how-quantumbpm-fits" class="hash-link" aria-label="Direct link to How QuantumBPM fits" title="Direct link to How QuantumBPM fits" translate="no">​</a></h2>
<p>QuantumBPM is a BPMN+DMN platform — squarely in the business-process camp. We're not trying to be Airflow's replacement. We don't ship dataset lineage, schedule catchup, or the data-engineering-shaped tooling those platforms exist to provide. We do ship:</p>
<ul>
<li class=""><strong>BPMN 2.0 process modelling and execution</strong> — events, tasks, gateways, scopes, compensation, multi-instance.</li>
<li class=""><strong>DMN 1.5 decision modelling</strong> — for the rules a business-rule task evaluates inside a process.</li>
<li class=""><strong>A web modeler, operational UI, and replay scrubber</strong> — for non-engineers who own the model.</li>
<li class=""><strong>Built on <a class="" href="https://quantumbpm.com/blog/bpmn-vs-temporal">Temporal</a></strong> — durable execution under the BPMN layer.</li>
</ul>
<p>If your problem is data orchestration, pick one of the three orchestrators above. If your problem is business processes, the <a class="" href="https://quantumbpm.com/comparison">comparison page</a> covers how QuantumBPM stacks up against Camunda and other BPMN engines.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-go-from-here">Where to go from here<a href="https://quantumbpm.com/blog/bpmn-vs-airflow-prefect#where-to-go-from-here" class="hash-link" aria-label="Direct link to Where to go from here" title="Direct link to Where to go from here" translate="no">​</a></h2>
<ul>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/what-is-bpmn">What is BPMN?</a></strong> — the BPMN primer.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/bpmn-vs-dmn">BPMN vs. DMN</a></strong> — process vs. decision modelling.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/bpmn-vs-temporal">BPMN vs. Temporal</a></strong> — the code-first orchestration comparison.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/bpmn-vs-n8n">BPMN vs. n8n</a></strong> — the visual-automation comparison.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/general/platform-overview">QuantumBPM platform overview</a></strong> — start here if you're modelling a real process.</li>
</ul>]]></content>
        <author>
            <name>Richard Bízik</name>
            <uri>https://www.linkedin.com/in/richard-b%C3%ADzik/</uri>
        </author>
        <category label="BPMN" term="BPMN"/>
        <category label="Decisioning" term="Decisioning"/>
        <category label="Engine" term="Engine"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[BPMN vs. n8n: When Visual Automation Hits Its Ceiling]]></title>
        <id>https://quantumbpm.com/blog/bpmn-vs-n8n</id>
        <link href="https://quantumbpm.com/blog/bpmn-vs-n8n"/>
        <updated>2026-05-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical comparison of n8n and BPMN engines — what each does well, where n8n stops scaling for business processes, and when to graduate to a BPMN engine.]]></summary>
        <content type="html"><![CDATA[<p><a href="https://n8n.io/" target="_blank" rel="noopener noreferrer" class="">n8n</a> is a popular open-core (under the <a href="https://docs.n8n.io/sustainable-use-license/" target="_blank" rel="noopener noreferrer" class="">Sustainable Use License</a>) workflow automation tool. It's a node-based visual editor with a large library of pre-built integrations, designed for connecting SaaS APIs, automating internal tasks, and replacing the kind of glue code that used to live in cron jobs and shell scripts. Most teams that adopt n8n do so to get something working in a day instead of a sprint — and that's exactly what it's good for.</p>
<p>It's also a tool that teams <strong>outgrow</strong> in a specific, predictable way. This post is about that ceiling: where n8n stops being the right answer, and what changes when you move to a BPMN engine.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-n8n-is-excellent-at">What n8n is excellent at<a href="https://quantumbpm.com/blog/bpmn-vs-n8n#what-n8n-is-excellent-at" class="hash-link" aria-label="Direct link to What n8n is excellent at" title="Direct link to What n8n is excellent at" translate="no">​</a></h2>
<p>Before the criticism, the credit. n8n is a fantastic fit when:</p>
<ul>
<li class="">You need to <strong>glue APIs together</strong> — pull from one SaaS, push to another, transform JSON in the middle.</li>
<li class="">The workflow is <strong>short</strong> — runs in seconds to minutes, triggered by a webhook, schedule, or polling.</li>
<li class="">The <strong>integration is the hard part</strong> — you'd rather drop a "Slack" node onto a canvas than read a Slack SDK reference.</li>
<li class="">The team running the workflow is <strong>mixed</strong> — engineers, ops, marketers, support — and a low-code visual editor lowers the bar.</li>
<li class="">The audit and durability requirements are <strong>modest</strong> — "did this workflow run, and what did it do?" is enough.</li>
</ul>
<p>For these cases n8n is genuinely faster than building anything in-house, and "use a BPMN engine instead" would be a bad recommendation. Don't do that.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-n8n-starts-hurting">Where n8n starts hurting<a href="https://quantumbpm.com/blog/bpmn-vs-n8n#where-n8n-starts-hurting" class="hash-link" aria-label="Direct link to Where n8n starts hurting" title="Direct link to Where n8n starts hurting" translate="no">​</a></h2>
<p>n8n earns its name from "node-mation" — a node graph for automations. That's a different shape from a <strong>business process</strong>, and the gap shows up as your needs grow:</p>
<ul>
<li class=""><strong>Long-running and stateful.</strong> n8n can sleep, schedule, and wait — but it isn't designed around weeks-long instances with rich scoped state. A BPMN engine is. Process instances live indefinitely, surviving restarts, with full event history.</li>
<li class=""><strong>Multi-actor, human-in-the-loop work.</strong> When a step is "wait for a compliance officer to approve this", n8n leans on third-party form/approval nodes. BPMN has <strong>user tasks</strong> as a first-class citizen with an API your own UI consumes (claim, complete, reassign).</li>
<li class=""><strong>Formal error semantics.</strong> BPMN distinguishes <em>errors</em> (something failed) from <em>escalations</em> (something needs human attention) from <em>compensation</em> (we have to undo work that already succeeded). Boundary events, event sub-processes, and compensation handlers all have spec-defined semantics. n8n has retries and "on error" branches, but not the same scoped, hierarchical model.</li>
<li class=""><strong>Versioning and migration of in-flight work.</strong> When the rules change, what happens to the orders already mid-flow? A BPMN engine treats every save as a new immutable definition version and gives you explicit migration plans. n8n's model is closer to "edit the workflow", which is fine for short-running automations and uncomfortable for long-running processes.</li>
<li class=""><strong>Audit trails the business actually needs.</strong> Regulated industries need "who decided what, when, with what inputs" for every instance, indefinitely. A BPMN engine paired with DMN gives you this by default. In n8n you build it.</li>
<li class=""><strong>Decisions as first-class artefacts.</strong> When the rules ("which loan tier?", "high-risk transaction?") are owned by non-engineers and change often, you want them as a <a class="" href="https://quantumbpm.com/blog/what-is-dmn">DMN model</a>, not as branching nodes inside a workflow.</li>
<li class=""><strong>Governance and review.</strong> A diagram with a stable XML serialisation, owned in git, reviewed as a model with proposed-change diffs — that's the BPMN flow. n8n's stored format isn't designed to be reviewed as a contract between engineering and the business.</li>
</ul>
<p>The pattern is consistent: n8n optimises for <strong>getting one automation done quickly</strong>. BPMN optimises for <strong>operating long-running, audited, multi-actor business processes at organisational scale</strong>. Different shapes, different tools.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-useful-rapid-test">A useful rapid test<a href="https://quantumbpm.com/blog/bpmn-vs-n8n#a-useful-rapid-test" class="hash-link" aria-label="Direct link to A useful rapid test" title="Direct link to A useful rapid test" translate="no">​</a></h2>
<p>Three questions, and if the answers tilt toward the right column, n8n is the right call. If they tilt left, you're in BPMN territory:</p>
<table><thead><tr><th>Question</th><th>BPMN territory</th><th>n8n territory</th></tr></thead><tbody><tr><td>How long does a typical instance live?</td><td>Hours to weeks</td><td>Seconds to minutes</td></tr><tr><td>Who reviews changes to the workflow?</td><td>Compliance, product, ops</td><td>The engineer who wrote it</td></tr><tr><td>What happens when the rules change mid-flight?</td><td>We migrate in-flight instances</td><td>We edit the workflow</td></tr><tr><td>What does an "error" mean?</td><td>A scoped, hierarchical thing with handlers and compensation</td><td>A retry or a fallback branch</td></tr><tr><td>Do humans approve, claim, or complete steps?</td><td>Often</td><td>Rarely</td></tr><tr><td>Is the audit trail a regulatory requirement?</td><td>Yes</td><td>"Logs are fine"</td></tr></tbody></table>
<p>If you're in the middle, you're probably running both — n8n for the fast integrations, a BPMN engine for the processes that matter to the business. They genuinely don't compete. They coexist.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-give-up-by-moving-to-bpmn">What you give up by moving to BPMN<a href="https://quantumbpm.com/blog/bpmn-vs-n8n#what-you-give-up-by-moving-to-bpmn" class="hash-link" aria-label="Direct link to What you give up by moving to BPMN" title="Direct link to What you give up by moving to BPMN" translate="no">​</a></h2>
<p>A BPMN engine isn't free. The trade-offs you make moving from n8n:</p>
<ul>
<li class=""><strong>No giant integration library.</strong> n8n's <a href="https://n8n.io/integrations/" target="_blank" rel="noopener noreferrer" class="">400+ pre-built nodes</a> are real engineering value. A BPMN engine's service tasks are typically powered by your own workers — you write them. You can absolutely call any API from a service task, but you write the call.</li>
<li class=""><strong>Higher modelling discipline.</strong> BPMN is a richer, more formal language. There are more ways to do something correctly <em>and</em> incorrectly. Onboarding a team takes longer than n8n.</li>
<li class=""><strong>More moving parts to operate.</strong> A BPMN engine usually wants Postgres and a durable execution substrate. n8n is comparatively self-contained.</li>
</ul>
<p>These are real costs, and they're why "rip out n8n" is rarely the right answer for the parts of your stack that n8n was a good fit for in the first place.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-quantumbpm-positions">How QuantumBPM positions<a href="https://quantumbpm.com/blog/bpmn-vs-n8n#how-quantumbpm-positions" class="hash-link" aria-label="Direct link to How QuantumBPM positions" title="Direct link to How QuantumBPM positions" translate="no">​</a></h2>
<p>QuantumBPM is a BPMN+DMN platform built in Go on <a class="" href="https://quantumbpm.com/blog/bpmn-vs-temporal">Temporal</a>. It's deliberately not in the same category as n8n — we don't ship a vast integration library, and our target user is engineering teams running long-running stateful processes that the business owns. Concretely:</p>
<ul>
<li class=""><strong>BPMN 2.0 modeler and engine</strong> — every event type, interrupting and non-interrupting boundary events, ad-hoc and event sub-processes, call activities, multi-instance, compensation.</li>
<li class=""><strong>DMN 1.5 integration</strong> — decisions are first-class artefacts, with FEEL, decision tables, simulation, and execution history.</li>
<li class=""><strong>Operational UI</strong> — running instances, replay slider, incidents, message/signal correlation, token modification, version migration.</li>
<li class=""><strong>External worker queue</strong> — a poll-based HTTP API for service tasks in any language. This is the n8n-shaped extension point: instead of pre-built nodes, you write workers that pull jobs.</li>
</ul>
<p>If you're at the point where n8n is hurting and you want to evaluate a BPMN engine that doesn't drag in a JVM platform, the <a class="" href="https://quantumbpm.com/comparison">comparison page</a> is a good starting place.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-go-from-here">Where to go from here<a href="https://quantumbpm.com/blog/bpmn-vs-n8n#where-to-go-from-here" class="hash-link" aria-label="Direct link to Where to go from here" title="Direct link to Where to go from here" translate="no">​</a></h2>
<ul>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/what-is-bpmn">What is BPMN?</a></strong> — the BPMN primer if you're new to the spec.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/bpmn-vs-dmn">BPMN vs. DMN</a></strong> — how decisions fit alongside processes.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/bpmn-vs-temporal">BPMN vs. Temporal</a></strong> — the code-first orchestration comparison.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/bpmn/overview">QuantumBPM overview</a></strong> — what's supported in the engine.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/bpmn/external-workers">External workers</a></strong> — how to plug in your integrations.</li>
</ul>
<p>If you've already decided n8n isn't enough and want to try modelling a real process, start at the <a class="" href="https://quantumbpm.com/docs/general/platform-overview">platform overview</a>.</p>]]></content>
        <author>
            <name>Richard Bízik</name>
            <uri>https://www.linkedin.com/in/richard-b%C3%ADzik/</uri>
        </author>
        <category label="BPMN" term="BPMN"/>
        <category label="Decisioning" term="Decisioning"/>
        <category label="Engine" term="Engine"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[BPMN vs. Temporal: When Do You Need a BPMN Engine?]]></title>
        <id>https://quantumbpm.com/blog/bpmn-vs-temporal</id>
        <link href="https://quantumbpm.com/blog/bpmn-vs-temporal"/>
        <updated>2026-05-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical comparison of BPMN engines and Temporal — what each is built for, where the line falls, and when a BPMN engine on top of Temporal is the right call.]]></summary>
        <content type="html"><![CDATA[<p>If you're building anything stateful and long-running on the JVM, in Go, or in TypeScript, <a href="https://temporal.io/" target="_blank" rel="noopener noreferrer" class="">Temporal</a> has probably crossed your desk. It's the de-facto durable execution platform — Uber, Snap, Coinbase, HashiCorp, Stripe, Datadog and a long tail of others run production workloads on it. The natural question, when someone hands you a "build a workflow engine" requirement, is: <strong>do I just use Temporal, or do I need a BPMN engine?</strong></p>
<p>Short answer: <strong>both can be right. The dividing line is who the model belongs to.</strong> This post explains why we built QuantumBPM <em>on top of</em> Temporal rather than competing with it, and how to decide which level you should be writing your workflow at.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="disclosure-up-front">Disclosure up front<a href="https://quantumbpm.com/blog/bpmn-vs-temporal#disclosure-up-front" class="hash-link" aria-label="Direct link to Disclosure up front" title="Direct link to Disclosure up front" translate="no">​</a></h2>
<p>QuantumBPM is built on Temporal. Every BPMN process instance is a Temporal workflow. So this post isn't "us vs them" — we're a layer on the same stack.<br>
<!-- -->For the architecture detail, see the <a class="" href="https://quantumbpm.com/comparison">Why QuantumBPM is built on Temporal</a> section of our comparison page.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-temporal-actually-is">What Temporal actually is<a href="https://quantumbpm.com/blog/bpmn-vs-temporal#what-temporal-actually-is" class="hash-link" aria-label="Direct link to What Temporal actually is" title="Direct link to What Temporal actually is" translate="no">​</a></h2>
<p>Temporal is a <strong>durable execution platform</strong>. You write workflows as ordinary code (Go, Java, Python, TS, Ruby, .NET, PHP) and the platform makes them survive crashes, restarts, network partitions, and weeks-long sleeps without you writing any "where was I?" recovery logic.</p>
<p>The mental model:</p>
<ul>
<li class="">A <strong>workflow</strong> is a function. It can <code>await</code> activities, sleep for arbitrary durations, receive signals, and spawn child workflows.</li>
<li class="">An <strong>activity</strong> is a piece of work with side effects — a database write, an HTTP call, a payment charge. Activities are retried, heartbeated, and recorded.</li>
<li class="">A <strong>signal</strong> is an external event delivered to a running workflow.</li>
<li class="">A <strong>query</strong> is a read-only inspection of workflow state.</li>
<li class="">The whole thing is <strong>event-sourced</strong>: every step is recorded, and replaying the events deterministically reconstructs the state.</li>
</ul>
<p>This is a small, sharp set of primitives. Once you internalise them, you can build anything stateful — and Temporal's whole value proposition is that you build it <em>in code</em>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-a-bpmn-engine-adds">What a BPMN engine adds<a href="https://quantumbpm.com/blog/bpmn-vs-temporal#what-a-bpmn-engine-adds" class="hash-link" aria-label="Direct link to What a BPMN engine adds" title="Direct link to What a BPMN engine adds" translate="no">​</a></h2>
<p>BPMN engines also model long-running stateful workflows. The difference is that the workflow lives as a <strong>declarative model</strong> — a diagram with well-defined runtime semantics — rather than as code.</p>
<p>That difference matters less than people think for engineers, and more than they think for organisations:</p>
<ul>
<li class="">A BPMN process is <strong>legible to people who don't write code</strong>. A product manager, an ops lead, a compliance officer can read the diagram, propose changes, sign off. With Temporal you ship a code review.</li>
<li class="">A BPMN process is <strong>versioned as a model</strong>. Deploying a new version, migrating in-flight instances to it, and auditing what version ran for a given instance are first-class concerns. With Temporal, workflow versioning is a code-side concern (the <code>Patch</code>/<code>GetVersion</code> APIs) that engineers reason about line-by-line.</li>
<li class="">A BPMN process <strong>comes with formal semantics for everything organisations actually need</strong>: scoped error handling, escalation, compensation, multi-instance, ad-hoc subprocesses, boundary events, message correlation, named errors. You'd build all of that yourself in Temporal — and most teams do, badly, then rebuild it.</li>
<li class="">A BPMN engine <strong>comes with a UI for operators</strong>: see running instances, scrub through history, resolve incidents, send messages, modify token state, migrate to a new version. Temporal Web is a developer tool for inspecting workflow histories — it's not aimed at non-engineering operators.</li>
</ul>
<p>So the line is roughly: <strong>Temporal gives you a primitive. A BPMN engine gives you a product.</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-raw-temporal-is-the-right-answer">When raw Temporal is the right answer<a href="https://quantumbpm.com/blog/bpmn-vs-temporal#when-raw-temporal-is-the-right-answer" class="hash-link" aria-label="Direct link to When raw Temporal is the right answer" title="Direct link to When raw Temporal is the right answer" translate="no">​</a></h2>
<p>You don't need a BPMN engine — and shouldn't pay for one — if all of the following are true:</p>
<ul>
<li class="">The workflow is <strong>owned and changed by engineers</strong>, not by product/ops/compliance.</li>
<li class="">The shape of the work isn't really business-process-shaped — it's, say, a data pipeline, a service orchestration, a saga across microservices, a deployment workflow.</li>
<li class="">You're already building polyglot <strong>service workers</strong> in Go/Java/Python/TS and the code-first model fits your team's mental model.</li>
<li class="">Operational tooling for non-engineers (a process map UI, an instance scrubber, an incident-resolution console) <strong>isn't a requirement</strong>.</li>
</ul>
<p>Temporal will be cheaper, simpler, and more flexible than putting a BPMN engine on top of it for these cases. It's the right tool.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-a-bpmn-engine-earns-its-keep">When a BPMN engine earns its keep<a href="https://quantumbpm.com/blog/bpmn-vs-temporal#when-a-bpmn-engine-earns-its-keep" class="hash-link" aria-label="Direct link to When a BPMN engine earns its keep" title="Direct link to When a BPMN engine earns its keep" translate="no">​</a></h2>
<p>A BPMN engine on top of Temporal — what we are — earns its keep when:</p>
<ul>
<li class="">The process is <strong>business-shaped</strong>: onboarding, claims, approvals, KYC, underwriting, fulfilment, case management. The vocabulary lines up with BPMN's primitives (tasks, gateways, events, sub-processes) because that's what BPMN was designed for.</li>
<li class=""><strong>Non-engineers need to read, change, or sign off the model.</strong> Compliance reviewing the auth flow as a diagram is qualitatively different from reviewing it as a Go file.</li>
<li class="">You need <strong>operational UIs</strong> out of the box: a list of running instances, a way to resolve incidents, a way to send a message to a stuck instance, a way to migrate in-flight work to a new version.</li>
<li class="">You need <strong>decisions with audit trails</strong> alongside the process. BPMN's business-rule task pairs with DMN — see <a class="" href="https://quantumbpm.com/blog/bpmn-vs-dmn">BPMN vs. DMN</a> for that integration.</li>
<li class=""><strong>Versioning matters at the process level</strong>, not just the code level — every change is a new immutable definition version, evaluable side-by-side, with a UI showing what version each instance ran on.</li>
</ul>
<p>You're not throwing Temporal away in this case. You're getting Temporal <em>plus</em> a layer that turns its primitives into a product.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-quantumbpm-is-concretely">What QuantumBPM is, concretely<a href="https://quantumbpm.com/blog/bpmn-vs-temporal#what-quantumbpm-is-concretely" class="hash-link" aria-label="Direct link to What QuantumBPM is, concretely" title="Direct link to What QuantumBPM is, concretely" translate="no">​</a></h2>
<p>To make the layering tangible: QuantumBPM is a Go service that hosts BPMN process definitions, exposes them via a REST/OpenAPI surface and a web modeler, and translates BPMN execution into Temporal workflows. On top of Temporal we add:</p>
<ul>
<li class=""><strong>Full BPMN 2.0 element coverage</strong> — every event type (timer, message, signal, error, escalation, compensation, link, terminate), interrupting and non-interrupting boundary events, event subprocesses, ad-hoc subprocesses, call activities, multi-instance.</li>
<li class=""><strong>Scope tree and event bubbling</strong> — compensation, escalation, and errors target <em>logical</em> scopes and traverse the active ancestry chain.</li>
<li class=""><strong>Concurrency-safe interpreter state</strong> for parallel and inclusive gateways.</li>
<li class=""><strong>Live instance modification</strong> — insert or cancel tokens on a running workflow.</li>
<li class=""><strong>Version migration</strong> — explicit migration plans move in-flight instances to a newer process version.</li>
<li class=""><strong>Replay slider UI</strong> — reconstructs process state at any point in Temporal's event history.</li>
<li class=""><strong>Inline DMN integration</strong> — business-rule tasks invoke registered DMN definitions in-process. No external decision-service round-trip.</li>
<li class=""><strong>External worker queue</strong> — HTTP poll API for service tasks that live outside the Temporal worker pool (e.g. languages without a Temporal SDK, or workers behind a firewall).</li>
<li class=""><strong>Visual modeler, projects, RBAC, audit history, multi-tenancy, OpenTelemetry, metrics</strong> — the platform layer that wraps the engine into a product.</li>
</ul>
<p>The split is clean: Temporal owns durability and execution. QuantumBPM owns the BPMN spec, the user-facing surfaces, and the operational controls.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-decision-shortcut">A decision shortcut<a href="https://quantumbpm.com/blog/bpmn-vs-temporal#a-decision-shortcut" class="hash-link" aria-label="Direct link to A decision shortcut" title="Direct link to A decision shortcut" translate="no">​</a></h2>
<p>Stop reading and pick the simpler tool when you can:</p>
<ul>
<li class="">The workflow is small, lives next to one service, and only engineers touch it → write it as a Temporal workflow.</li>
<li class="">The workflow is the <em>product</em> — visible to non-engineers, audited, versioned, owned by the business → use a BPMN engine.</li>
<li class="">You're already on Temporal and outgrowing the code-only model → BPMN-on-Temporal is the natural next step.</li>
</ul>
<p>If you're not sure, the cost of starting with raw Temporal and migrating later is usually lower than the cost of adopting a BPMN engine you don't need yet.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-go-from-here">Where to go from here<a href="https://quantumbpm.com/blog/bpmn-vs-temporal#where-to-go-from-here" class="hash-link" aria-label="Direct link to Where to go from here" title="Direct link to Where to go from here" translate="no">​</a></h2>
<ul>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/what-is-bpmn">What is BPMN?</a></strong> — the core BPMN primer.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/bpmn-vs-dmn">BPMN vs. DMN</a></strong> — pairing process and decision modelling.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/comparison">QuantumBPM comparison</a></strong> — the full architecture and competitor comparison, including the detailed Temporal section.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/bpmn/overview">BPMN overview</a></strong> — the engine's supported element surface.</li>
</ul>
<p>If you're already running Temporal and curious what the BPMN layer adds, the <a class="" href="https://quantumbpm.com/docs/general/platform-overview">platform overview</a> is the fastest way in.</p>]]></content>
        <author>
            <name>Richard Bízik</name>
            <uri>https://www.linkedin.com/in/richard-b%C3%ADzik/</uri>
        </author>
        <category label="BPMN" term="BPMN"/>
        <category label="Engine" term="Engine"/>
        <category label="Decisioning" term="Decisioning"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[What is DMN? A Practical Guide for Engineers]]></title>
        <id>https://quantumbpm.com/blog/what-is-dmn</id>
        <link href="https://quantumbpm.com/blog/what-is-dmn"/>
        <updated>2026-04-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[An engineer-focused introduction to DMN (Decision Model and Notation) — what it is, why teams use it, and how a real decision is modeled, evaluated, and audited.]]></summary>
        <content type="html"><![CDATA[<p>DMN — <strong>Decision Model and Notation</strong> — is an <a href="https://www.omg.org/dmn/" target="_blank" rel="noopener noreferrer" class="">OMG</a> standard for describing operational business decisions. It gives you a visual, vendor-neutral way to express the rules that take an input context, apply business logic, and return an answer — and crucially, the model is <em>directly executable</em>. The same diagram a domain expert reviews is the artefact a runtime evaluates.</p>
<p>This post is the engineer's-eye view: what DMN is, why teams reach for it instead of <code>if/else</code> in code, and what the moving parts are in a real decision.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-dmn-exists">Why DMN exists<a href="https://quantumbpm.com/blog/what-is-dmn#why-dmn-exists" class="hash-link" aria-label="Direct link to Why DMN exists" title="Direct link to Why DMN exists" translate="no">​</a></h2>
<p>Most non-trivial systems carry rules that change far more often than the surrounding code:</p>
<ul>
<li class="">A pricing engine adjusts discount tiers every quarter.</li>
<li class="">A KYC workflow tightens thresholds whenever a regulator publishes new guidance.</li>
<li class="">A clinical triage system updates symptom-to-priority mapping when protocols change.</li>
</ul>
<p>These rules are owned — in practice — by people who don't ship code: product managers, compliance officers, clinicians, underwriters. DMN is the contract between them and the engineering organization. The domain expert reads and edits a decision table. The engine evaluates it deterministically. The audit log shows which rules fired and why.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-two-pieces-of-dmn-youll-actually-use">The two pieces of DMN you'll actually use<a href="https://quantumbpm.com/blog/what-is-dmn#the-two-pieces-of-dmn-youll-actually-use" class="hash-link" aria-label="Direct link to The two pieces of DMN you'll actually use" title="Direct link to The two pieces of DMN you'll actually use" translate="no">​</a></h2>
<p>The DMN spec is large, but in day-to-day work two artefacts carry the weight.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-the-decision-requirements-graph-drg">1. The Decision Requirements Graph (DRG)<a href="https://quantumbpm.com/blog/what-is-dmn#1-the-decision-requirements-graph-drg" class="hash-link" aria-label="Direct link to 1. The Decision Requirements Graph (DRG)" title="Direct link to 1. The Decision Requirements Graph (DRG)" translate="no">​</a></h3>
<p>A DRG is a directed graph that lays out <em>which decisions exist</em> and <em>what they depend on</em>. Nodes come in a small set of flavours:</p>
<table><thead><tr><th>Node type</th><th>What it represents</th></tr></thead><tbody><tr><td><strong>Decision</strong></td><td>A unit that produces an output by evaluating an expression.</td></tr><tr><td><strong>Input data</strong></td><td>A variable that flows in from the caller.</td></tr><tr><td><strong>Business knowledge model (BKM)</strong></td><td>Reusable invocable logic — a function-like artefact a decision can call.</td></tr><tr><td><strong>Knowledge source</strong></td><td>A pointer to authoritative documentation (a regulation, a policy doc). Not evaluated.</td></tr><tr><td><strong>Decision service</strong></td><td>A bundle of decisions exposed as a single callable unit.</td></tr></tbody></table>
<p>Arrows are dependencies: "this decision needs that input data" or "this decision depends on that other decision". The DRG is what you see in the modeler before you open any individual decision.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-the-decision-logic--usually-a-decision-table">2. The decision logic — usually a decision table<a href="https://quantumbpm.com/blog/what-is-dmn#2-the-decision-logic--usually-a-decision-table" class="hash-link" aria-label="Direct link to 2. The decision logic — usually a decision table" title="Direct link to 2. The decision logic — usually a decision table" translate="no">​</a></h3>
<p>Every decision contains a <strong>boxed expression</strong>. The most common form is the <strong>decision table</strong>, but the spec also defines literal expressions, contexts, lists, relations, function definitions, and invocations — each rendered as its own visual box.</p>
<p>A decision table has a hit policy, input columns, output columns, and rules:</p>
<table><thead><tr><th>U</th><th>Age</th><th>Credit Score</th><th><strong>Loan Approved</strong></th></tr></thead><tbody><tr><td>1</td><td><code>&lt; 18</code></td><td>-</td><td>false</td></tr><tr><td>2</td><td><code>&gt;= 18</code></td><td><code>&gt; 700</code></td><td>true</td></tr><tr><td>3</td><td><code>&gt;= 18</code></td><td><code>&lt;= 700</code></td><td>false</td></tr></tbody></table>
<p>The <code>U</code> is the <strong>hit policy</strong> — <em>Unique</em>, meaning rules may not overlap. Exactly one row matches. Other common policies you'll see:</p>
<ul>
<li class=""><code>F</code> (First) — top-down, first match wins.</li>
<li class=""><code>P</code> (Priority) — rules may overlap. Output is chosen by configured priority.</li>
<li class=""><code>C</code> (Collect) — return all matches as a list (with optional aggregations for sum/min/max).</li>
<li class=""><code>A</code> (Any) — overlaps allowed, but every matching rule must produce the same output.</li>
</ul>
<p>The expressions inside cells aren't an ad-hoc DSL — they're written in <strong>FEEL</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="feel--the-expression-language">FEEL — the expression language<a href="https://quantumbpm.com/blog/what-is-dmn#feel--the-expression-language" class="hash-link" aria-label="Direct link to FEEL — the expression language" title="Direct link to FEEL — the expression language" translate="no">​</a></h2>
<p><strong>FEEL</strong> (Friendly Enough Expression Language) is the small declarative language defined by the DMN spec. It's the language used for input entries, output entries, literal expressions, conditions — anywhere DMN needs to evaluate something.</p>
<p>FEEL supports the things you'd expect — arithmetic, booleans, strings, lists, contexts (records), dates, times, durations, ranges, <code>if</code>/<code>then</code>/<code>else</code>, <code>for</code> comprehensions, quantified expressions (<code>some</code>, <code>every</code>), and a sizeable standard library of built-ins.</p>
<p>A few concrete examples:</p>
<div class="language-feel codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-feel codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">// Arithmetic</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gross * 0.20</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">// Range test (used as an input entry in a decision table)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[18..65]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">// List comprehension</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">sum(for o in orders return o.total)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">// Quantified expression</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">every order in orders satisfies order.status = "approved"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">// Context literal — values returned from decisions are often contexts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{ approved: true, reason: "credit_ok" }</span><br></span></code></pre></div></div>
<p>What makes FEEL useful in this setting is that it is <em>deliberately</em> not a general-purpose programming language. There are no side effects, no I/O, no loops with mutable state — just pure expressions. That property is what makes a decision auditable and replayable.</p>
<p>If you want to play with FEEL without spinning up a project, the <a href="https://feel-playground.quantumbpm.com/" target="_blank" rel="noopener noreferrer" class="">QuantumBPM FEEL playground</a> is a browser-based editor — same LSP, same evaluator, no signup. Paste an expression, see the result.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-evaluating-a-decision-actually-looks-like">What evaluating a decision actually looks like<a href="https://quantumbpm.com/blog/what-is-dmn#what-evaluating-a-decision-actually-looks-like" class="hash-link" aria-label="Direct link to What evaluating a decision actually looks like" title="Direct link to What evaluating a decision actually looks like" translate="no">​</a></h2>
<p>In QuantumBPM, evaluating a decision is an HTTP call against a definition. The minimum you need is the <em>decision name</em> and an <em>input context</em>:</p>
<div class="language-http codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-http codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">POST /api/projects/{project}/definitions/{definition}/evaluate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Content-Type: application/json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "decisionName": "Loan Approved",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "context": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "Age": 32,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "Credit Score": 720</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p>The response gives you the result, plus the per-decision execution detail — which rules fired, what each upstream decision returned, and the dependency tree the evaluation traversed. That last part matters: a real-world DRG is not a single decision but a graph, and every transitively-required decision is evaluated and recorded.</p>
<p>For a fuller worked example, see the <a class="" href="https://quantumbpm.com/docs/dmn/overview">DMN overview</a> and <a class="" href="https://quantumbpm.com/docs/dmn/evaluation">Evaluation and history</a> docs.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-not-just-write-it-in-code">"Why not just write it in code?"<a href="https://quantumbpm.com/blog/what-is-dmn#why-not-just-write-it-in-code" class="hash-link" aria-label="Direct link to &quot;Why not just write it in code?&quot;" title="Direct link to &quot;Why not just write it in code?&quot;" translate="no">​</a></h2>
<p>This is the question every engineer asks the first time they see DMN. Three honest answers:</p>
<ol>
<li class=""><strong>Rules change on a different cadence than the surrounding code.</strong> Putting them in a model that non-engineers can read, edit, simulate, and version separately is genuinely faster than the round-trip of a code change every time a threshold moves.</li>
<li class=""><strong>The audit trail is non-negotiable in regulated industries.</strong> A DMN engine records the inputs, the rules that fired, and the outputs for every evaluation. Reproducing that with hand-rolled code is a project, not an afternoon.</li>
<li class=""><strong>The model is testable as a model.</strong> You can simulate proposed rule changes against historical traffic without redeploying anything — a workflow QuantumBPM exposes natively.</li>
</ol>
<p>DMN is not the right tool for everything. If the logic is small, stable, and lives next to a single piece of code, native code is fine. DMN earns its keep where logic is <em>shared</em>, <em>changing</em>, <em>audited</em>, or <em>owned by a non-engineering team</em>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-dmn-sits-next-to-bpmn">How DMN sits next to BPMN<a href="https://quantumbpm.com/blog/what-is-dmn#how-dmn-sits-next-to-bpmn" class="hash-link" aria-label="Direct link to How DMN sits next to BPMN" title="Direct link to How DMN sits next to BPMN" translate="no">​</a></h2>
<p>The two most-cited OMG standards in this space are DMN and <strong>BPMN</strong> (Business Process Model and Notation). They solve different problems and are designed to be used together:</p>
<ul>
<li class=""><strong>BPMN</strong> describes a process — a sequence of tasks, gateways, events — <em>over time</em>. "What happens, in what order, in response to what."</li>
<li class=""><strong>DMN</strong> describes a decision — <em>at a single point in time</em>. "Given these inputs, what's the answer."</li>
</ul>
<p>A BPMN business-rule task calls a DMN decision. The process engine handles flow, scheduling, retries, timers, human tasks. The decision engine handles "what's the loan amount" or "is this transaction high-risk." We covered the split in detail in <a class="" href="https://quantumbpm.com/blog/bpmn-vs-dmn">BPMN vs. DMN: when to use which</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-go-from-here">Where to go from here<a href="https://quantumbpm.com/blog/what-is-dmn#where-to-go-from-here" class="hash-link" aria-label="Direct link to Where to go from here" title="Direct link to Where to go from here" translate="no">​</a></h2>
<ul>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/what-is-bpmn">What is BPMN?</a></strong> — the companion piece on process modelling.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/dmn/overview">The DMN overview</a></strong> — what's supported, the modeler, and links to the element reference.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/dmn/feel/overview">FEEL syntax</a></strong> — the expression language in depth.</li>
<li class=""><strong><a href="https://feel-playground.quantumbpm.com/" target="_blank" rel="noopener noreferrer" class="">FEEL playground</a></strong> — try and share FEEL expressions in the browser. Share links so teammates can pick up your work without any setup.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/dmn/expressions/decision-table">Decision tables</a></strong> — hit policies, input/output columns, and worked examples.</li>
</ul>
<p>If you want to try a decision in QuantumBPM end-to-end — model it, evaluate it, inspect the audit trail — start at the <a class="" href="https://quantumbpm.com/docs/general/platform-overview">getting started guide</a>.</p>]]></content>
        <author>
            <name>Richard Bízik</name>
            <uri>https://www.linkedin.com/in/richard-b%C3%ADzik/</uri>
        </author>
        <category label="DMN" term="DMN"/>
        <category label="Decisioning" term="Decisioning"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[What is BPMN? The 20% of the Spec You'll Actually Use]]></title>
        <id>https://quantumbpm.com/blog/what-is-bpmn</id>
        <link href="https://quantumbpm.com/blog/what-is-bpmn"/>
        <updated>2026-04-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A developer-focused introduction to BPMN 2.0 — what it is, the small set of elements that cover most real processes, and how a BPMN model becomes an executing workflow.]]></summary>
        <content type="html"><![CDATA[<p>BPMN — <strong>Business Process Model and Notation</strong> — is the <a href="https://www.omg.org/bpmn/" target="_blank" rel="noopener noreferrer" class="">OMG</a> standard for diagramming business processes. It defines a visual language (rectangles for tasks, diamonds for gateways, circles for events)an XML serialisation. Modern BPMN engines treat the diagram as something <em>directly executable</em> — the same model a business analyst draws is what the engine runs.</p>
<p>The BPMN 2.0 spec defines well over a hundred symbols. The honest truth is that you'll use about fifteen of them in 90% of real processes. This post walks through that core, then explains how a BPMN model actually executes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-bpmn-is-good-at">What BPMN is good at<a href="https://quantumbpm.com/blog/what-is-bpmn#what-bpmn-is-good-at" class="hash-link" aria-label="Direct link to What BPMN is good at" title="Direct link to What BPMN is good at" translate="no">​</a></h2>
<p>BPMN models the <em>flow of work over time</em>: who or what does the next step, what triggers it, what happens if it times out, and what runs in parallel. It's the right tool when:</p>
<ul>
<li class="">A piece of work spans <strong>multiple actors</strong> — a service, a human, an external system.</li>
<li class="">It runs over <strong>wall-clock time</strong> — minutes, hours, weeks.</li>
<li class="">It needs to <strong>survive crashes, restarts, and retries</strong> without losing its place.</li>
<li class="">The flow itself is a thing the business owns — onboarding, claims processing, an approval chain — and changes over time.</li>
</ul>
<p>If your "process" is a synchronous function call that returns in milliseconds, BPMN is overkill. If your "process" reaches a step labelled <em>"wait two business days for the customer to upload a document"</em>, BPMN earns its keep.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-core-elements">The core elements<a href="https://quantumbpm.com/blog/what-is-bpmn#the-core-elements" class="hash-link" aria-label="Direct link to The core elements" title="Direct link to The core elements" translate="no">​</a></h2>
<p>A BPMN process is a directed graph of <strong>flow elements</strong> connected by <strong>sequence flows</strong> (the arrows). The flow elements come in three families.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="events--circles">Events — circles<a href="https://quantumbpm.com/blog/what-is-bpmn#events--circles" class="hash-link" aria-label="Direct link to Events — circles" title="Direct link to Events — circles" translate="no">​</a></h3>
<p>Events represent <em>something that happens</em>. Three positions on a flow:</p>
<ul>
<li class=""><strong>Start events</strong> — how the process begins.</li>
<li class=""><strong>End events</strong> — how it terminates.</li>
<li class=""><strong>Intermediate events</strong> — something in the middle: wait for a message, throw a signal, raise an error.</li>
</ul>
<p>Each event has a <em>trigger type</em>. The ones you'll meet in real processes:</p>
<table><thead><tr><th></th><th>Trigger</th><th>What it means</th></tr></thead><tbody><tr><td><img src="https://quantumbpm.com/img/bpmn/start-event-none.svg" alt="" width="32"></td><td><strong>None</strong></td><td>Plain start/end with no specific trigger.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/start-event-message.svg" alt="" width="32"></td><td><strong>Message</strong></td><td>Wait for a named message correlated to this instance.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/start-event-signal.svg" alt="" width="32"></td><td><strong>Signal</strong></td><td>Broadcast or wait for a named signal (one-to-many).</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/start-event-timer.svg" alt="" width="32"></td><td><strong>Timer</strong></td><td>Fire after a duration, on a date, or on a cycle.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/start-event-error.svg" alt="" width="32"></td><td><strong>Error</strong></td><td>Throw or catch a named error — for failure handling.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/start-event-escalation.svg" alt="" width="32"></td><td><strong>Escalation</strong></td><td>Like an error, but typically non-interrupting (the work continues while someone is alerted).</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/start-event-compensation.svg" alt="" width="32"></td><td><strong>Compensation</strong></td><td>Trigger compensating actions when something has to be "undone".</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/end-event-terminate.svg" alt="" width="32"></td><td><strong>Terminate</strong></td><td>An end event that immediately stops the entire process.</td></tr></tbody></table>
<p>Boundary events sit on the edge of a task or sub-process and intercept it — "if this task takes longer than 24 hours, fire a timer". They come in <strong>interrupting</strong> (cancel the task) and <strong>non-interrupting</strong> (run alongside) variants.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tasks--rounded-rectangles">Tasks — rounded rectangles<a href="https://quantumbpm.com/blog/what-is-bpmn#tasks--rounded-rectangles" class="hash-link" aria-label="Direct link to Tasks — rounded rectangles" title="Direct link to Tasks — rounded rectangles" translate="no">​</a></h3>
<p>A task is a unit of work. The task type tells the engine <em>who or what</em> does it:</p>
<table><thead><tr><th></th><th>Task</th><th>Performed by</th></tr></thead><tbody><tr><td><img src="https://quantumbpm.com/img/bpmn/service-task.svg" alt="" width="32"></td><td><strong>Service task</strong></td><td>An automated worker — typically code (a Temporal worker, a polled HTTP worker, etc.).</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/user-task.svg" alt="" width="32"></td><td><strong>User task</strong></td><td>A person, via your UI. The engine holds the token until the task is claimed and completed.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/script-task.svg" alt="" width="32"></td><td><strong>Script task</strong></td><td>A short inline expression — in QuantumBPM, written in <a href="https://feel-playground.quantumbpm.com/" target="_blank" rel="noopener noreferrer" class="">FEEL</a>.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/business-rule-task.svg" alt="" width="32"></td><td><strong>Business-rule task</strong></td><td>Calls a DMN decision and writes the result back into process variables.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/send-task.svg" alt="" width="32"> <img src="https://quantumbpm.com/img/bpmn/receive-task.svg" alt="" width="32"></td><td><strong>Send task</strong> / <strong>Receive task</strong></td><td>Send or receive a message.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/manual-task.svg" alt="" width="32"> <img src="https://quantumbpm.com/img/bpmn/task-none.svg" alt="" width="32"></td><td><strong>Manual task</strong> / <strong>Generic task</strong></td><td>Untracked manual work / no specific semantics — useful for documenting steps the engine doesn't run.</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="gateways--diamonds">Gateways — diamonds<a href="https://quantumbpm.com/blog/what-is-bpmn#gateways--diamonds" class="hash-link" aria-label="Direct link to Gateways — diamonds" title="Direct link to Gateways — diamonds" translate="no">​</a></h3>
<p>Gateways control branching and merging:</p>
<table><thead><tr><th></th><th>Gateway</th><th>Behaviour</th></tr></thead><tbody><tr><td><img src="https://quantumbpm.com/img/bpmn/gateway-xor.svg" alt="" width="32"></td><td><strong>Exclusive (XOR)</strong></td><td>One outgoing path is taken based on a condition. The default <code>if/else</code> of BPMN.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/gateway-parallel.svg" alt="" width="32"></td><td><strong>Parallel (AND)</strong></td><td>All outgoing paths run concurrently. On join, all incoming must arrive.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/gateway-or.svg" alt="" width="32"></td><td><strong>Inclusive (OR)</strong></td><td>Any number of outgoing paths can run, based on per-flow conditions.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/gateway-eventbased.svg" alt="" width="32"></td><td><strong>Event-based</strong></td><td>Wait for one of several events. Whichever fires first wins.</td></tr></tbody></table>
<p>Three families. About fifteen meaningful elements. That covers most processes you'll actually model.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="structure-sub-processes-and-call-activities">Structure: sub-processes and call activities<a href="https://quantumbpm.com/blog/what-is-bpmn#structure-sub-processes-and-call-activities" class="hash-link" aria-label="Direct link to Structure: sub-processes and call activities" title="Direct link to Structure: sub-processes and call activities" translate="no">​</a></h2>
<p>Real processes get nested. BPMN gives you three ways to compose:</p>
<table><thead><tr><th></th><th>Element</th><th>What it is</th></tr></thead><tbody><tr><td><img src="https://quantumbpm.com/img/bpmn/subprocess-expanded.svg" alt="" width="32"></td><td><strong>Embedded sub-process</strong></td><td>A group of elements drawn inline, sharing the parent's data.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/call-activity.svg" alt="" width="32"></td><td><strong>Call activity</strong></td><td>An invocation of <em>another</em> process definition. The called process runs as its own scope and can be reused across processes.</td></tr><tr><td><img src="https://quantumbpm.com/img/bpmn/event-subprocess-expanded.svg" alt="" width="32"></td><td><strong>Event sub-process</strong></td><td>Sits inside a parent scope and triggers on an event (a message, an error, a timer). Useful for "if anything goes wrong, do this".</td></tr></tbody></table>
<p>Sub-processes are also where you attach <strong>boundary events</strong> for scoped error handling, escalation, and compensation.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-small-example">A small example<a href="https://quantumbpm.com/blog/what-is-bpmn#a-small-example" class="hash-link" aria-label="Direct link to A small example" title="Direct link to A small example" translate="no">​</a></h2>
<p>Here's the spine of an order-fulfilment process modelled in QuantumBPM:</p>
<p><img decoding="async" loading="lazy" alt="Order-fulfilment process modelled in the QuantumBPM modeler" src="https://quantumbpm.com/assets/images/order-fulfilment-b31401ac9c08cf9733c35f1658420a22.png" width="1250" height="345" class="img_ev3q"></p>
<p>Reading left to right:</p>
<ol>
<li class=""><strong>Start event</strong> (message: "OrderPlaced") — the process kicks off when an order arrives.</li>
<li class=""><strong>Business-rule task</strong> — call a DMN decision to decide whether the order needs manual review.</li>
<li class=""><strong>Exclusive gateway</strong> — branch on the decision result.<!-- -->
<ul>
<li class=""><strong>No review needed</strong> → continue.</li>
<li class=""><strong>Review needed</strong> → <strong>user task</strong> (a human approves or rejects), then continue.</li>
</ul>
</li>
<li class=""><strong>Service task</strong> — charge the customer.<!-- -->
<ul>
<li class="">With a <strong>timer boundary event</strong> — if charging takes more than 5 minutes, escalate to manual charge.</li>
</ul>
</li>
<li class=""><strong>Service task</strong> — schedule shipment.</li>
<li class=""><strong>End event</strong>.</li>
</ol>
<p>That's an end-to-end process using start/end, a business-rule task, a service task, a user task, an exclusive gateway and a timer boundary event. Six element types — and you can already model surprisingly complex real-world flows.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-executing-a-bpmn-model-actually-means">What "executing a BPMN model" actually means<a href="https://quantumbpm.com/blog/what-is-bpmn#what-executing-a-bpmn-model-actually-means" class="hash-link" aria-label="Direct link to What &quot;executing a BPMN model&quot; actually means" title="Direct link to What &quot;executing a BPMN model&quot; actually means" translate="no">​</a></h2>
<p>The visual model is just one face of BPMN. Underneath, every BPMN element has well-defined runtime semantics: what it does when a token arrives, what it produces, what it waits for. A BPMN engine is the runtime that gives those semantics a concrete implementation.</p>
<p>In QuantumBPM, that runtime is built on <a href="https://temporal.io/" target="_blank" rel="noopener noreferrer" class="">Temporal</a> — a durable execution platform. Each process instance becomes a Temporal workflow. The practical consequences:</p>
<ul>
<li class=""><strong>Crashes are non-events.</strong> Workflow state is event-sourced, so a worker restart resumes the instance exactly where it stopped — no recovery code to write.</li>
<li class=""><strong>Long-running is normal.</strong> A timer event waiting two weeks doesn't pin a thread or a database row in a non-obvious way. Durability is the default.</li>
<li class=""><strong>Every step is recorded.</strong> The instance history is replayable — the same property that lets us offer a "scrub the timeline" UI for running and completed instances.</li>
</ul>
<p>What we layer on top is the BPMN-specific machinery: the element catalog with full validation, scope trees for compensation/escalation/error bubbling, a concurrency-safe interpreter for parallel and inclusive gateways, and the operational tooling — incidents, message/signal correlation, token modification, version migration.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-go-from-here">Where to go from here<a href="https://quantumbpm.com/blog/what-is-bpmn#where-to-go-from-here" class="hash-link" aria-label="Direct link to Where to go from here" title="Direct link to Where to go from here" translate="no">​</a></h2>
<ul>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/what-is-dmn">What is DMN?</a></strong> — the companion piece on decision modelling.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/bpmn-vs-dmn">BPMN vs. DMN</a></strong> — how the two standards complement each other.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/bpmn/overview">BPMN overview</a></strong> — what's supported in the QuantumBPM engine and the modeler.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/bpmn/elements/events">Element reference</a></strong> — events, tasks, gateways, structure, flows.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/bpmn/external-workers">External workers</a></strong> — how to implement service tasks in your own language.</li>
</ul>
<p>If you want to draw and run a process end-to-end, start at the <a class="" href="https://quantumbpm.com/docs/general/platform-overview">platform overview</a>.</p>]]></content>
        <author>
            <name>Richard Bízik</name>
            <uri>https://www.linkedin.com/in/richard-b%C3%ADzik/</uri>
        </author>
        <category label="BPMN" term="BPMN"/>
        <category label="Decisioning" term="Decisioning"/>
        <category label="Engine" term="Engine"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[BPMN vs. DMN: When to Use Which (and When to Use Both)]]></title>
        <id>https://quantumbpm.com/blog/bpmn-vs-dmn</id>
        <link href="https://quantumbpm.com/blog/bpmn-vs-dmn"/>
        <updated>2026-04-12T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical comparison of BPMN and DMN — what each standard models, where they overlap, where they don't, and how a real system uses them together.]]></summary>
        <content type="html"><![CDATA[<p>BPMN and DMN are two of the most-cited <a href="https://www.omg.org/" target="_blank" rel="noopener noreferrer" class="">OMG</a> standards in business automation, and they're often confused. The short version: <strong>BPMN models <em>processes over time</em>. DMN models <em>decisions at a point in time</em>.</strong> They're complementary, not competitors. Most non-trivial systems end up using both.</p>
<p>This post walks through what each standard is, where each one fits, the boundary between them, and a worked example of the two working together.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-30-second-answer">The 30-second answer<a href="https://quantumbpm.com/blog/bpmn-vs-dmn#the-30-second-answer" class="hash-link" aria-label="Direct link to The 30-second answer" title="Direct link to The 30-second answer" translate="no">​</a></h2>
<table><thead><tr><th></th><th><strong>BPMN</strong></th><th><strong>DMN</strong></th></tr></thead><tbody><tr><td>Full name</td><td>Business Process Model and Notation</td><td>Decision Model and Notation</td></tr><tr><td>Models</td><td>A <em>process</em> — a flow of work over time</td><td>A <em>decision</em> — inputs to outputs at one moment</td></tr><tr><td>Visual primitive</td><td>Tasks, gateways, events on a flow</td><td>A graph of decisions plus boxed expressions (often decision tables)</td></tr><tr><td>Statefulness</td><td>Stateful — each instance has a position, variables, history</td><td>Stateless — given the same inputs, you get the same outputs</td></tr><tr><td>Time-aware?</td><td>Yes — timers, durations, deadlines, recurring schedules</td><td>No — evaluation is instantaneous</td></tr><tr><td>Concurrency model</td><td>First-class — parallel/inclusive gateways, boundary events</td><td>None — pure expression evaluation</td></tr><tr><td>Expression language</td><td>FEEL (commonly)</td><td>FEEL (always)</td></tr><tr><td>Typical question</td><td>"What happens next?"</td><td>"What's the answer?"</td></tr></tbody></table>
<p>If you take only one thing away: <strong>a BPMN business-rule task calls a DMN decision.</strong> That single pattern is how most systems combine them.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-bpmn-models">What BPMN models<a href="https://quantumbpm.com/blog/bpmn-vs-dmn#what-bpmn-models" class="hash-link" aria-label="Direct link to What BPMN models" title="Direct link to What BPMN models" translate="no">​</a></h2>
<p>BPMN is a flow diagram for work that unfolds over time. It answers questions like:</p>
<ul>
<li class="">"When an order arrives, what runs first, and under what conditions does the next step run?"</li>
<li class="">"If the customer hasn't responded in 48 hours, what happens?"</li>
<li class="">"Three things need to run in parallel — when they're all done, then what?"</li>
</ul>
<p>BPMN's primitives are tasks (units of work), gateways (branching and merging), events (things that happen), and structural containers (sub-processes, call activities). Crucially, BPMN is <strong>stateful</strong>: a process instance has a current position (the <em>tokens</em> on the diagram), variables, and a history. It can wait. It can fail and resume. It can run for weeks.</p>
<p>For more on BPMN itself, see <a class="" href="https://quantumbpm.com/blog/what-is-bpmn">What is BPMN?</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-dmn-models">What DMN models<a href="https://quantumbpm.com/blog/bpmn-vs-dmn#what-dmn-models" class="hash-link" aria-label="Direct link to What DMN models" title="Direct link to What DMN models" translate="no">​</a></h2>
<p>DMN is for the bit of work that <em>isn't</em> about flow — it's about figuring out an answer. It answers questions like:</p>
<ul>
<li class="">"Given this customer's age, income, and credit score, what loan tier do they qualify for?"</li>
<li class="">"Given this transaction, is it high-risk?"</li>
<li class="">"Given this clinical input, what's the triage priority?"</li>
</ul>
<p>DMN's primitives are decisions, input data, business knowledge models, and decision services, organised in a Decision Requirements Graph. The logic inside each decision is a <strong>boxed expression</strong> — usually a decision table.</p>
<p>DMN is <strong>stateless</strong>. Given the same inputs, a decision always returns the same outputs. There's no concept of waiting, no concurrency, no time progression — just expressions over inputs. That's a feature: it's what makes decisions cheap to evaluate, easy to test, and trivially auditable.</p>
<p>For more on DMN itself, see <a class="" href="https://quantumbpm.com/blog/what-is-dmn">What is DMN?</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-they-overlap-and-dont">Where they overlap (and don't)<a href="https://quantumbpm.com/blog/bpmn-vs-dmn#where-they-overlap-and-dont" class="hash-link" aria-label="Direct link to Where they overlap (and don't)" title="Direct link to Where they overlap (and don't)" translate="no">​</a></h2>
<p>Some surface-level overlap can confuse newcomers, so it's worth being explicit:</p>
<p><strong>Both use FEEL.</strong> FEEL is the expression language defined inside the DMN spec, but it's used inside BPMN too — for sequence flow conditions, script tasks, and I/O mappings. One language across both surfaces is a significant ergonomic win when you have it. in QuantumBPM, FEEL is the script language for BPMN as well as the expression language for DMN. You can try it in the browser at the <a href="https://feel-playground.quantumbpm.com/" target="_blank" rel="noopener noreferrer" class="">FEEL playground</a>.</p>
<p><strong>Both can express conditional logic.</strong> You <em>can</em> model <code>if age &lt; 18 reject, else approve</code> as a chain of BPMN exclusive gateways. You <em>can</em> also model a long-running multi-step approval flow inside a single DMN function.<br>
<!-- -->Both are bad ideas. BPMN gateways are the wrong level of abstraction for evaluating a rule set. DMN has no concept of waiting or human tasks. Use each for what it's designed for.</p>
<p><strong>Neither is the other's parent.</strong> DMN is sometimes described as "a part of BPMN" — it isn't. They're separate specifications, governed independently, and DMN is genuinely useful even with no BPMN anywhere in the picture. A pure decision API (no process around it) is a perfectly common DMN use case.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-they-work-together">How they work together<a href="https://quantumbpm.com/blog/bpmn-vs-dmn#how-they-work-together" class="hash-link" aria-label="Direct link to How they work together" title="Direct link to How they work together" translate="no">​</a></h2>
<p>The integration point in the BPMN spec is the <strong>business-rule task</strong>. It's a task that delegates to a decision engine, passes in the current process variables, and writes the decision's output back into the process state. The pattern looks like this:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">[Start] → [Service task: fetch customer]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       → [Business-rule task: "Loan Approval"]   ← calls DMN</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       → [Exclusive gateway: approved?]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ├─ yes → [Service task: disburse funds] → [End]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            └─ no  → [User task: notify customer]   → [End]</span><br></span></code></pre></div></div>
<p>The DMN side is just a decision (or a small DRG) named <em>Loan Approval</em> with inputs like <code>age</code>, <code>income</code>, <code>creditScore</code> and an output <code>{ approved: boolean, tier: string }</code>. The BPMN side handles everything else: pulling data, branching, waiting, escalating, retrying, recording.</p>
<p>In QuantumBPM, the business-rule task invokes registered DMN definitions in-process, so there's no external decision-service round-trip — the BPMN engine and the DMN engine live in the same product and share the same project, identity, and audit history. See the <a class="" href="https://quantumbpm.com/docs/bpmn/overview">BPMN overview</a> and <a class="" href="https://quantumbpm.com/docs/dmn/overview">DMN overview</a> for the supported feature surface on each side.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-heuristic-which-one-do-i-need">A heuristic: which one do I need?<a href="https://quantumbpm.com/blog/bpmn-vs-dmn#a-heuristic-which-one-do-i-need" class="hash-link" aria-label="Direct link to A heuristic: which one do I need?" title="Direct link to A heuristic: which one do I need?" translate="no">​</a></h2>
<p>When you're sketching a new system, ask:</p>
<ol>
<li class=""><strong>Does this thing run over time, with multiple steps that have to happen in some order?</strong> → BPMN.</li>
<li class=""><strong>Does this thing involve waiting — for a human, for an external system, for a timer?</strong> → BPMN.</li>
<li class=""><strong>Does this thing need to survive crashes, restarts, and resume mid-flight?</strong> → BPMN.</li>
<li class=""><strong>Does this thing take inputs and return an answer, with no waiting and no side effects?</strong> → DMN.</li>
<li class=""><strong>Are the rules being changed by non-engineers?</strong> → almost always DMN, regardless of where they sit.</li>
<li class=""><strong>Does the thing need both — flow <em>and</em> decisions inside the flow?</strong> → both, with DMN called from BPMN business-rule tasks.</li>
</ol>
<p>The mistake is to lean too hard on either side. A pure-BPMN model with twenty exclusive gateways is unreadable. A pure-DMN model that tries to encode "wait for the customer to upload a document" can't. Use the right tool for the right shape of problem.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-go-from-here">Where to go from here<a href="https://quantumbpm.com/blog/bpmn-vs-dmn#where-to-go-from-here" class="hash-link" aria-label="Direct link to Where to go from here" title="Direct link to Where to go from here" translate="no">​</a></h2>
<ul>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/what-is-bpmn">What is BPMN?</a></strong> — the BPMN primer.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/what-is-dmn">What is DMN?</a></strong> — the DMN primer.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/bpmn/overview">BPMN overview</a></strong> and <strong><a class="" href="https://quantumbpm.com/docs/dmn/overview">DMN overview</a></strong> — what's supported in QuantumBPM.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/comparison">Why QuantumBPM ships both</a></strong> — how a unified BPMN + DMN platform compares to running two stacks.</li>
</ul>
<p>If you want to model a process that calls a decision end-to-end in a single product, start at the <a class="" href="https://quantumbpm.com/docs/general/platform-overview">platform overview</a>.</p>]]></content>
        <author>
            <name>Richard Bízik</name>
            <uri>https://www.linkedin.com/in/richard-b%C3%ADzik/</uri>
        </author>
        <category label="BPMN" term="BPMN"/>
        <category label="DMN" term="DMN"/>
        <category label="Decisioning" term="Decisioning"/>
        <category label="Engine" term="Engine"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Building a BPMN engine on Temporal]]></title>
        <id>https://quantumbpm.com/blog/bpmn-on-temporal</id>
        <link href="https://quantumbpm.com/blog/bpmn-on-temporal"/>
        <updated>2026-04-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Why we built QuantumBPM's BPMN engine on top of Temporal instead of writing our own durable execution substrate — and what BPMN gives Temporal developers that raw Temporal doesn't.]]></summary>
        <content type="html"><![CDATA[<p>When we started designing QuantumBPM's process engine, we ran into the same wall every workflow tool runs into: how do you make execution durable? Survive worker crashes, network partitions, weeks-long timers, replay after restart, exactly-once activity semantics? The honest answer turned out to be: <strong>don't build that yourself</strong>.</p>
<p>This post is about the bet we made — running BPMN on top of <a href="https://temporal.io/" target="_blank" rel="noopener noreferrer" class="">Temporal</a> — what it cost us, what it bought us, and why we think Temporal developers are the audience that benefits the most from a BPMN layer sitting above their existing investment.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-bet">The bet<a href="https://quantumbpm.com/blog/bpmn-on-temporal#the-bet" class="hash-link" aria-label="Direct link to The bet" title="Direct link to The bet" translate="no">​</a></h2>
<p>A BPMN engine is two distinct pieces of software glued together. One half is a <em>durable execution substrate</em> — the code that survives crashes, replays workflow history deterministically, schedules timers across days and weeks, fans out to workers, retries with backoff, and keeps state consistent under concurrent execution. The other half is the <em>BPMN-specific machinery</em> — element semantics, scope hierarchies, compensation handlers, message correlation, the modeler, the operations UI, the replay scrubber, version migration, RBAC, audit history.</p>
<p>Camunda's bet was to build both halves. Camunda 8's <a href="https://camunda.com/platform/zeebe/" target="_blank" rel="noopener noreferrer" class="">Zeebe</a> is a Raft-based event-sourced workflow broker built on top of <a href="https://github.com/atomix/atomix" target="_blank" rel="noopener noreferrer" class="">Atomix</a> — a from-scratch durable execution engine designed specifically for BPMN. It's a defensible bet, but it isn't a free one.</p>
<p>Two consequences of that bet are worth being specific about, because they shaped our thinking.</p>
<p><strong>The substrate is yours forever, including the parts you'd rather not maintain.</strong> Zeebe's consensus layer is a Java fork of the original Atomix. Upstream Atomix moved to Go some years ago and is now an entirely different project — leaving Camunda effectively the maintainer of the Java consensus library underneath their engine. Every layer you build yourself is a layer you maintain yourself, indefinitely. The unglamorous layers (consensus, log replication, storage formats) accumulate maintenance the same way the glamorous ones do.</p>
<p><strong>Decoupling the engine from observability creates structural drift.</strong> Camunda 8's runtime is decoupled from <strong>Operate</strong>, their separate operations product, and synced through Elasticsearch exporters. Those exporters are eventually consistent: events flow from the broker through exporters into Elasticsearch, and Operate reads from Elasticsearch. Operators regularly report Operate falling behind reality, showing stale state, or missing events when the broker has already moved on. That isn't a bug — it's a structural property of an architecture that splits the engine and the operational view into separate products communicating asynchronously.</p>
<p>Our bet was different:</p>
<blockquote>
<p>Durable execution is a solved problem. BPMN semantics are not. Build on Temporal and put our engineering effort into the layer where the actual product lives.</p>
</blockquote>
<p>Temporal is funded, well-staffed, and runs in production at Uber, Snap, Coinbase, HashiCorp, Stripe, and Datadog among many others. The storage layer, the replay engine, the event sourcing, the SDK story across seven languages — none of that is ours to maintain. Our team gets to spend its time on the BPMN spec, on the modeler, on the operations UI, on simulation, on DMN integration. The layers users actually see.</p>
<p>The shape of the architecture also avoids the observability drift problem. Our operations UI reads BPMN process state by replaying directly from Temporal's workflow history (<code>GetProcessStateFromHistory</code>) — there's no separate exporter pipeline, no Elasticsearch sync, no "the engine says one thing and the UI says another." If Temporal has the event, we have the event. If we don't, neither does Temporal.</p>
<p>That's the bet. The rest of this post is what fell out of it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-temporal-gives-us-for-free">What Temporal gives us, for free<a href="https://quantumbpm.com/blog/bpmn-on-temporal#what-temporal-gives-us-for-free" class="hash-link" aria-label="Direct link to What Temporal gives us, for free" title="Direct link to What Temporal gives us, for free" translate="no">​</a></h2>
<p>Mapping BPMN concepts onto Temporal primitives turned out to be remarkably clean:</p>
<ul>
<li class=""><strong>A BPMN process instance</strong> is a Temporal workflow.</li>
<li class=""><strong>Service tasks, user tasks, script tasks</strong> become activities or signal-receiving blocks inside the workflow.</li>
<li class=""><strong>Messages and signals</strong> become Temporal signals.</li>
<li class=""><strong>Timer events</strong> become Temporal timers.</li>
<li class=""><strong>Call activities</strong> become Temporal child workflows.</li>
<li class=""><strong>Variables</strong> live in workflow-local state, replayed deterministically with the workflow.</li>
<li class=""><strong>Boundary events and event subprocesses</strong> are scoped goroutines (<code>workflow.Go</code>) tied to the parent's cancellation context.</li>
</ul>
<p>Once that mapping clicked, a long list of capabilities came along essentially for free:</p>
<ul>
<li class=""><strong>Durable execution.</strong> A worker crash mid-process is invisible to the engine. The instance resumes from the next event in its history.</li>
<li class=""><strong>Long-running is the default.</strong> A process instance waiting two weeks for a customer document doesn't pin a database row or a goroutine in any non-obvious way. Temporal sized for one workflow scales to the next million the same way.</li>
<li class=""><strong>Event-sourced history.</strong> Every step is recorded. This is what powers our <strong>replay scrubber</strong> in the operations UI — given any process instance, we can reconstruct the BPMN-level state at any point in its execution from <code>GetProcessStateFromHistory</code>.</li>
<li class=""><strong>Polyglot workers.</strong> A service task can be implemented as a Temporal activity in any of Temporal's seven SDK languages (Go, Java, Python, TypeScript, .NET, PHP, Ruby), or — for languages without a Temporal SDK, or workers that need to live outside the Temporal pool — as an HTTP poll-based external worker in any language with an HTTP client.</li>
<li class=""><strong>Standard storage.</strong> Postgres, MySQL, or Cassandra — pick one. There is no proprietary log format to operate, no custom storage engine to babysit.</li>
</ul>
<p>That's the substrate. None of it is novel; Temporal has been doing it well for years. The point is what we <em>don't</em> have to build.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-we-had-to-build-on-top">What we had to build on top<a href="https://quantumbpm.com/blog/bpmn-on-temporal#what-we-had-to-build-on-top" class="hash-link" aria-label="Direct link to What we had to build on top" title="Direct link to What we had to build on top" translate="no">​</a></h2>
<p>Temporal alone is not a BPMN engine. It is a primitive — a set of building blocks for writing durable workflows in code. Turning it into a BPMN runtime required a non-trivial amount of work:</p>
<ul>
<li class=""><strong>Full BPMN 2.0 element coverage.</strong> Every event type (timer, message, signal, error, escalation, compensation, link, terminate), interrupting and non-interrupting boundary events, event subprocesses, ad-hoc subprocesses, call activities, multi-instance, standard loops.</li>
<li class=""><strong>Scope tree and event bubbling.</strong> BPMN compensation, escalation, and errors target <em>logical</em> scopes. They traverse the active ancestry chain, not the static graph — so a re-entered subprocess resolves correctly to the currently-live ancestor. A naive Temporal implementation can't handle this; we maintain a deterministic scope hierarchy on every process instance.</li>
<li class=""><strong>Cancellable scope goroutines.</strong> <code>workflow.Go</code> does not inherit cancellation from arbitrary parent contexts — a footgun we hit early. Our <code>BPMNContext</code> derives node-scoped contexts that are cancelled correctly when an interrupting boundary event fires.</li>
<li class=""><strong>Concurrency-safe state for query handlers.</strong> Temporal query handlers run on a separate goroutine from the workflow's main execution and can read workflow state concurrently with mutations from inside the workflow itself. We protect <code>InterpreterState</code> with <code>sync.RWMutex</code> so an in-flight <code>getProcessState</code> query never observes a partially-mutated history slice or scope-tree map. This is what makes our replay scrubber UI safe to poll continuously against a running instance.</li>
<li class=""><strong>Live instance modification.</strong> Insert a token before a node, cancel a token, on a running instance, without restarting the workflow. Exposed via the API today.</li>
<li class=""><strong>Version migration.</strong> Explicit migration plans move in-flight instances to a newer process-definition version. This is the part of <code>Patch</code>/<code>GetVersion</code> that everyone struggles with, made into a first-class operation on a typed graph.</li>
<li class=""><strong>Replay slider UI.</strong> Reconstructs BPMN state at any point in the Temporal history and lets operators scrub through the timeline of an instance.</li>
<li class=""><strong>Inline DMN integration.</strong> Business-rule tasks invoke registered DMN definitions in-process — no external decision-service round-trip. The decision evaluation is recorded in the BPMN execution history alongside the activity that called it.</li>
<li class=""><strong>External worker queue.</strong> A HTTP poll API for service tasks that need to live outside the Temporal worker pool — languages without a Temporal SDK, workers behind a firewall, or teams who prefer the polling model.</li>
<li class=""><strong>The platform layer.</strong> Visual modeler, projects, RBAC, audit history, multi-tenancy, OpenTelemetry, Prometheus metrics — what wraps the engine into a product.</li>
</ul>
<p>The split is clean. <strong>Temporal owns durability and execution. QuantumBPM owns the BPMN spec, the user-facing surfaces, and the operational controls.</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-gives-temporal-developers-back">What this gives Temporal developers back<a href="https://quantumbpm.com/blog/bpmn-on-temporal#what-this-gives-temporal-developers-back" class="hash-link" aria-label="Direct link to What this gives Temporal developers back" title="Direct link to What this gives Temporal developers back" translate="no">​</a></h2>
<p>If you're already running Temporal, you are not the audience that needs to be convinced BPMN is "an executable diagram language" — you already write executable workflows. The question is what BPMN gives you that your current setup doesn't.</p>
<p>The honest answer, from our side:</p>
<p><strong>1. A diagram for the things engineers don't own.</strong> Temporal Web is a great tool — for engineers. It shows event histories, workflow histories, activity logs. It does not give a product manager, an ops engineer, a compliance officer, or a support rep a way to see what an instance is doing. A BPMN diagram does. The same artefact you ship to engineering becomes the artefact you give to the business.</p>
<p><strong>2. Versioning that operators can reason about.</strong> Most Temporal teams have a war story about <code>Patch</code>/<code>GetVersion</code>. Our migration plans turn version bumps into a typed operation on a typed graph: "instances at node X move to node Y in the new version, instances at node A stay where they are, this branch becomes that branch." Still hard, but no longer line-by-line code archaeology.</p>
<p><strong>3. Compensation and saga as a primitive, not a pattern.</strong> BPMN compensation handlers have spec-defined semantics that have been sharpened over fifteen years. If you've ever shipped a Temporal saga with a subtly broken compensation order, BPMN's named-error + compensation-handler model is a real upgrade. You can keep your existing Temporal workflows; just model the saga-shaped parts in BPMN and call them as child workflows.</p>
<p><strong>4. Human-in-the-loop without rolling your own.</strong> User tasks are a first-class BPMN element with a typed completion API. We hold the token; you build a UI on top via our REST API. No need to invent your own task-list table, claim/release/reassign protocol, or escalation timer wiring.</p>
<p><strong>5. DMN as a primitive your Temporal workflows can call.</strong> This is genuinely useful even without adopting BPMN. Define your business rules — pricing tiers, eligibility checks, risk scoring — in a versioned DMN model, and call them from inside an existing Temporal activity using our SDK. You get versioning, audit trails, and the ability for non-engineers to edit the rules without touching your Go workflow code.</p>
<p><strong>6. An operations UI sized for non-engineers.</strong> Running instances list, incident resolution, message/signal correlation, token modification, replay scrubbing — all in a UI that doesn't assume the user reads workflow histories for breakfast.</p>
<p>The integration story matters too: a Temporal team running on a self-hosted cluster or on Temporal Cloud doesn't need a second durable execution engine; QuantumBPM is designed to run against the Temporal you already operate.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-isnt">What this isn't<a href="https://quantumbpm.com/blog/bpmn-on-temporal#what-this-isnt" class="hash-link" aria-label="Direct link to What this isn't" title="Direct link to What this isn't" translate="no">​</a></h2>
<p>To be honest about scope: this isn't an "operations UI for any Temporal workflow you already wrote." Today our scrubber understands BPMN-shaped workflows specifically — the visual reconstruction depends on the BPMN scope tree we maintain. Generalising the replay UI to arbitrary Temporal workflows is on our minds, but it is not what ships today.</p>
<p>What ships today is a BPMN engine that runs as a Temporal application, integrates with the Temporal infrastructure you have, and gives you the BPMN-shaped layer on top. If your problem is shaped like a business process — onboarding, claims, approvals, fulfilment, KYC, case management, anything human-and-system-and-time — that's the right shape to model in BPMN, and Temporal is the right substrate underneath.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-start">Where to start<a href="https://quantumbpm.com/blog/bpmn-on-temporal#where-to-start" class="hash-link" aria-label="Direct link to Where to start" title="Direct link to Where to start" translate="no">​</a></h2>
<p>If you're a Temporal developer curious about whether the BPMN layer fits your team:</p>
<ul>
<li class=""><strong><a class="" href="https://quantumbpm.com/comparison">QuantumBPM comparison</a></strong> — the architectural deep-dive on what we built on top of Temporal.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/blog/bpmn-vs-temporal">BPMN vs. Temporal</a></strong> — the honest decision framework: when raw Temporal is right, when a BPMN engine on top earns its keep.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/bpmn/overview">BPMN overview</a></strong> — what's supported in the engine.</li>
<li class=""><strong><a class="" href="https://quantumbpm.com/docs/general/platform-overview">Platform overview</a></strong> — quickstart for self-hosting locally with <code>docker-compose</code>.</li>
</ul>
<p>The BPMN engine is one half of QuantumBPM. The other half is a <a class="" href="https://quantumbpm.com/blog/what-is-dmn">DMN 1.5 decision engine</a> that runs in the same product and shares the same project, identity, and audit history. The two compose naturally — BPMN's business-rule task calls DMN — and that pairing is, for us, the actual reason BPMN-on-Temporal earns its keep over raw Temporal alone.</p>
<p>If you have feedback, war stories about BPMN, Temporal, or the line between them — we'd genuinely like to hear it. Reach us at <a href="mailto:support@quantumbpm.com" target="_blank" rel="noopener noreferrer" class="">support@quantumbpm.com</a>.</p>]]></content>
        <author>
            <name>Richard Bízik</name>
            <uri>https://www.linkedin.com/in/richard-b%C3%ADzik/</uri>
        </author>
        <category label="BPMN" term="BPMN"/>
        <category label="Temporal" term="Temporal"/>
        <category label="Engine" term="Engine"/>
    </entry>
</feed>