What is DMN? A Practical Guide for Engineers
DMN — Decision Model and Notation — is an OMG 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 directly executable. The same diagram a domain expert reviews is the artefact a runtime evaluates.
This post is the engineer's-eye view: what DMN is, why teams reach for it instead of if/else in code, and what the moving parts are in a real decision.
Why DMN exists
Most non-trivial systems carry rules that change far more often than the surrounding code:
- A pricing engine adjusts discount tiers every quarter.
- A KYC workflow tightens thresholds whenever a regulator publishes new guidance.
- A clinical triage system updates symptom-to-priority mapping when protocols change.
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.
The two pieces of DMN you'll actually use
The DMN spec is large, but in day-to-day work two artefacts carry the weight.
1. The Decision Requirements Graph (DRG)
A DRG is a directed graph that lays out which decisions exist and what they depend on. Nodes come in a small set of flavours:
| Node type | What it represents |
|---|---|
| Decision | A unit that produces an output by evaluating an expression. |
| Input data | A variable that flows in from the caller. |
| Business knowledge model (BKM) | Reusable invocable logic — a function-like artefact a decision can call. |
| Knowledge source | A pointer to authoritative documentation (a regulation, a policy doc). Not evaluated. |
| Decision service | A bundle of decisions exposed as a single callable unit. |
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.
2. The decision logic — usually a decision table
Every decision contains a boxed expression. The most common form is the decision table, but the spec also defines literal expressions, contexts, lists, relations, function definitions, and invocations — each rendered as its own visual box.
A decision table has a hit policy, input columns, output columns, and rules:
| U | Age | Credit Score | Loan Approved |
|---|---|---|---|
| 1 | < 18 | - | false |
| 2 | >= 18 | > 700 | true |
| 3 | >= 18 | <= 700 | false |
The U is the hit policy — Unique, meaning rules may not overlap. Exactly one row matches. Other common policies you'll see:
F(First) — top-down, first match wins.P(Priority) — rules may overlap. Output is chosen by configured priority.C(Collect) — return all matches as a list (with optional aggregations for sum/min/max).A(Any) — overlaps allowed, but every matching rule must produce the same output.
The expressions inside cells aren't an ad-hoc DSL — they're written in FEEL.
FEEL — the expression language
FEEL (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.
FEEL supports the things you'd expect — arithmetic, booleans, strings, lists, contexts (records), dates, times, durations, ranges, if/then/else, for comprehensions, quantified expressions (some, every), and a sizeable standard library of built-ins.
A few concrete examples:
// Arithmetic
gross * 0.20
// Range test (used as an input entry in a decision table)
[18..65]
// List comprehension
sum(for o in orders return o.total)
// Quantified expression
every order in orders satisfies order.status = "approved"
// Context literal — values returned from decisions are often contexts
{ approved: true, reason: "credit_ok" }
What makes FEEL useful in this setting is that it is deliberately 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.
If you want to play with FEEL without spinning up a project, the QuantumBPM FEEL playground is a browser-based editor — same LSP, same evaluator, no signup. Paste an expression, see the result.
What evaluating a decision actually looks like
In QuantumBPM, evaluating a decision is an HTTP call against a definition. The minimum you need is the decision name and an input context:
POST /api/projects/{project}/definitions/{definition}/evaluate
Content-Type: application/json
{
"decisionName": "Loan Approved",
"context": {
"Age": 32,
"Credit Score": 720
}
}
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.
For a fuller worked example, see the DMN overview and Evaluation and history docs.
"Why not just write it in code?"
This is the question every engineer asks the first time they see DMN. Three honest answers:
- Rules change on a different cadence than the surrounding code. 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.
- The audit trail is non-negotiable in regulated industries. 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.
- The model is testable as a model. You can simulate proposed rule changes against historical traffic without redeploying anything — a workflow QuantumBPM exposes natively.
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 shared, changing, audited, or owned by a non-engineering team.
How DMN sits next to BPMN
The two most-cited OMG standards in this space are DMN and BPMN (Business Process Model and Notation). They solve different problems and are designed to be used together:
- BPMN describes a process — a sequence of tasks, gateways, events — over time. "What happens, in what order, in response to what."
- DMN describes a decision — at a single point in time. "Given these inputs, what's the answer."
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 BPMN vs. DMN: when to use which.
Where to go from here
- What is BPMN? — the companion piece on process modelling.
- The DMN overview — what's supported, the modeler, and links to the element reference.
- FEEL syntax — the expression language in depth.
- FEEL playground — try and share FEEL expressions in the browser. Share links so teammates can pick up your work without any setup.
- Decision tables — hit policies, input/output columns, and worked examples.
If you want to try a decision in QuantumBPM end-to-end — model it, evaluate it, inspect the audit trail — start at the getting started guide.