---
title: 'Business Process Modeling'
source: 'https://academia.sh/en/courses/enterprise-context/business-process-modeling'
course: 'Enterprise Context and Integration'
language: en
updated: '2026-08-23T07:01:06+00:00'
license: 'CC BY-SA 4.0'
---

# Business Process Modeling

Modeling a business process step by step and sorting every step into three classes — fully automatic, requiring human judgment, outside the system: deriving the automation boundary from the model, the number of actors and owners the process passes through, and the number of wrong decisions and rollbacks produced by automating a step that requires human judgment by forcing the boundary.

The previous two lessons treated the enterprise as a static structure: systems, owners,
capabilities, records. But a business capability is a single row in the inventory, yet as it
happens it is a process that unfolds step by step. Behind the "loan issuance" row are dozens of
operations lined up from the card scan to the security tag, and not all of them happen inside
software. This lesson opens up that row and ties down where automation stops with a rule.

## A Process Is a Step Sequence

Process notations differ in their symbol set; no brand or notation name is written here. What they
share is this: every step has an **actor**, a set of **inputs**, and an **output**. Once these
three fields are written down, the notation itself becomes secondary, because the fields are what
can be measured.

An actor is not always a system. The fee being collected at the counter, and the security tag
being deactivated, are both steps of the process; both have an actor outside software. A process
model's first job is not to delete these steps but to **classify** them. Three classes are used:
fully automatic, requiring human judgment, outside the system.

Classification is not left to opinion, it is derived from the model (**EA9**): a step is automatic
only if every one of its inputs comes from a data asset that **has a writer**, and no information
item the decision needs falls outside the data model. This rule separates two different obstacles
from each other. The first is that the information exists nowhere — a material's damage degree is
in no data asset. The second is that the information appears to exist as a data asset, but no
system writes it; the legacy record in the enterprise model is like this, and it is called
**ownerless data**.

```js
// enterprise/model.mjs — MODEL regional library network: systems, owners, capabilities, data.
// Fictional; no real institution, vendor, product, or person is described.
export const SYSTEM = {
  catalog: { owner: "external-provider", budget: "service-fee" },
  loan: { owner: "it-department", budget: "internal-development" },
  billing: { owner: "it-department", budget: "internal-development" },
  membership: { owner: "member-services", budget: "member-services" },
  identity: { owner: "municipal-it", budget: "municipality" },
  "branch-local": { owner: "branch-management", budget: "branch" },
  kiosk: { owner: "branch-management", budget: "branch" },
  reporting: { owner: "management-unit", budget: "management" },
  archive: { owner: "none", budget: "none" },
};
// CAPABILITY — the business capabilities the enterprise must cover (a list independent of system)
export const CAPABILITY = ["material-search", "loan-issuance", "return-intake", "reservation",
  "membership-enrollment", "member-verification", "fee-calculation", "fee-collection",
  "inter-branch-transfer", "asset-count", "usage-reporting",
  "purchase-suggestion", "overdue-notification"];
// COVERS[s] = the capabilities system s claims to cover
export const COVERS = {
  catalog: ["material-search", "asset-count"],
  loan: ["loan-issuance", "return-intake", "reservation", "overdue-notification"],
  billing: ["fee-calculation", "overdue-notification"],
  membership: ["membership-enrollment", "member-verification"],
  identity: ["member-verification"],
  "branch-local": ["return-intake", "inter-branch-transfer", "asset-count"],
  kiosk: ["loan-issuance", "material-search"],
  reporting: ["usage-reporting"],
  archive: [],
};
// DATA[v] = data asset; which system writes it, which ones read it
export const DATA = {
  "member-record": { writes: ["membership"], reads: ["loan", "billing", "kiosk", "reporting"] },
  "identity-match": { writes: ["identity", "membership"], reads: ["loan", "kiosk"] },
  "material-record": { writes: ["catalog"], reads: ["loan", "kiosk", "branch-local", "reporting"] },
  "copy-status": { writes: ["catalog", "loan", "branch-local"], reads: ["kiosk", "reporting"] },
  "loan-transaction": { writes: ["loan", "kiosk"], reads: ["billing", "reporting"] },
  "fee-record": { writes: ["billing"], reads: ["membership", "reporting", "kiosk"] },
  "penalty-rule": { writes: ["billing"], reads: ["loan", "kiosk"] },
  "transfer-request": { writes: ["branch-local"], reads: ["loan", "catalog"] },
  "legacy-record": { writes: [], reads: ["archive", "reporting"] },
  "count-discrepancy": { writes: ["branch-local"], reads: [] },
};
export const SYSTEMS = Object.keys(SYSTEM);
export const owner = (s) => SYSTEM[s].owner;
// edge = the directed pair from the system that writes a data asset to the system that reads it
export function edges() {
  const e = new Map();
  for (const [v, d] of Object.entries(DATA))
    for (const w of d.writes) for (const r of d.reads)
      if (w !== r) e.set(`${w}->${r}`, [...(e.get(`${w}->${r}`) ?? []), v]);
  return e;
}
```

## Measurement

The second file models the loan checkout process as sixteen steps, derives classification from
the rule, and runs both boundaries over the same two hundred transactions. How often steps
requiring human judgment occur, how many steps a wrong decision rolls back, and how many systems
the fix requires writing to are chosen values (**EA10**). The probability of a wrong decision per
missing information item was taken as 0.15; that is the source of the threshold, and its
sensitivity is printed separately (**EA11**).

```js
// enterprise/process.mjs — loan checkout process: step classes, automation boundary, cost of forcing it
import { DATA, owner } from "./model.mjs";

const col = (s, n) => String(s).padEnd(n);
// STEP — MODEL loan checkout process; system null means the step happens outside software (counter, shelf).
// missing = the number of information items the step needs but that appear in no data asset.
const STEP = [
  { name: "member scans card", system: "kiosk", input: [] },
  { name: "identity is verified", system: "identity", input: ["identity-match"] },
  { name: "membership status is queried", system: "membership", input: ["member-record"] },
  { name: "unpaid fee is checked", system: "billing", input: ["fee-record"] },
  { name: "accrued fee is collected at the counter", system: null, input: [] },
  { name: "material barcode is scanned", system: "kiosk", input: ["material-record"] },
  { name: "copy status is queried", system: "catalog", input: ["copy-status"] },
  { name: "transfer is opened for a copy at another branch", system: "branch-local", input: ["copy-status"],
    missing: 2, frequency: 0.12, rollbackSteps: 3, fix: ["branch-local", "catalog", "loan"] },
  { name: "material's damage degree is recorded", system: "loan", input: ["material-record"],
    missing: 1, frequency: 0.06, rollbackSteps: 2, fix: ["loan", "billing"] },
  { name: "loan period is calculated", system: "loan", input: ["penalty-rule", "member-record"] },
  { name: "researcher extension is granted", system: "loan", input: ["member-record"],
    missing: 2, frequency: 0.04, rollbackSteps: 2, fix: ["loan", "membership"] },
  { name: "debt in the legacy record is queried", system: "loan", input: ["legacy-record"],
    frequency: 0.09, rollbackSteps: 4, fix: ["loan", "billing", "reporting"] },
  { name: "loan record is written", system: "loan", input: ["member-record"] },
  { name: "copy status is updated", system: "loan", input: ["copy-status"] },
  { name: "security tag is deactivated", system: null, input: [] },
  { name: "overdue notification is scheduled", system: "loan", input: ["loan-transaction", "penalty-rule"] },
];
// Automation boundary rule: a step can only be automated if every one of its inputs is a data
// asset with a writer, and no information item it needs falls outside the data model.
const unsourced = (a) => a.input.filter((v) => DATA[v].writes.length === 0);
function classify(a) {
  if (a.system === null) return ["non-system", "happens outside any system"];
  if (a.missing) return ["human-decision", `${a.missing} information item(s) in no data asset`];
  if (unsourced(a).length) return ["human-decision", `data with no writer: ${unsourced(a)[0]}`];
  return ["automatic", "-"];
}

console.log(col("step", 50) + col("actor", 15) + col("class", 16) + "reason");
console.log("-".repeat(102));
for (const a of STEP) {
  const [s, n] = classify(a);
  console.log(col(a.name, 50) + col(a.system ?? "counter/shelf", 15) + col(s, 16) + n);
}

const byClass = (s) => STEP.filter((a) => classify(a)[0] === s);
let longestRun = 0, streak = 0;
for (const a of STEP) { streak = classify(a)[0] === "automatic" ? streak + 1 : 0; longestRun = Math.max(longestRun, streak); }
const actor = (a) => a.system ?? "counter/shelf";
const stepOwner = (a) => (a.system ? owner(a.system) : "branch-management");
const handoff = STEP.slice(1).filter((a, i) => actor(a) !== actor(STEP[i]));
const ownerCrossing = STEP.slice(1).filter((a, i) => stepOwner(a) !== stepOwner(STEP[i]));
console.log(`\n${STEP.length} steps: ${byClass("automatic").length} automatic, ` +
  `${byClass("human-decision").length} human decision, ${byClass("non-system").length} non-system`);
console.log(`longest unbroken automatic run: ${longestRun} steps`);
console.log(`handoffs: ${handoff.length}, ${ownerCrossing.length} of which change owner; ` +
  `the process passes through ${new Set(STEP.map(actor)).size} actors and ${new Set(STEP.map(stepOwner)).size} owners`);

// ---- forcing the boundary: if steps that require human judgment are automated ----
const P = 0.15; // chosen rule: probability of a wrong decision per missing information item
const wrongProb = (a) => 1 - (1 - P) ** (a.missing ?? 1);
const makeRandom = (t) => { let s = t >>> 0; return () => (s = (s * 1664525 + 1013904223) >>> 0) / 2 ** 32; };
const rand = makeRandom(90210); // seed is visible; the same seed gives the same numbers
const N = 200;
const humanSteps = byClass("human-decision");
let touches = 0, wrong = 0, rolledBack = 0, fixWrites = 0, crossOwnerFixes = 0;
for (let i = 0; i < N; i++)
  for (const a of humanSteps) {
    if (rand() >= a.frequency) continue;
    touches++;
    if (rand() >= wrongProb(a)) continue;
    wrong++; rolledBack += a.rollbackSteps; fixWrites += a.fix.length;
    if (new Set(a.fix.map(owner)).size > 1) crossOwnerFixes++;
  }

console.log(`\n${N} loan transactions, seed 90210, wrong-decision probability per item ${P}`);
console.log(col("boundary", 18) + col("human touches", 16) + col("wrong decisions", 17) +
  col("rolled-back steps", 19) + "fix writes");
console.log("-".repeat(84));
console.log(col("current", 18) + col(touches, 16) + col(0, 17) + col(0, 19) + 0);
console.log(col("forced", 18) + col(0, 16) + col(wrong, 17) + col(rolledBack, 19) + fixWrites);
console.log(`\nthe forced boundary avoids ${touches} human touches, and produces ${wrong} wrong ` +
  `decisions in exchange`);
console.log(`${crossOwnerFixes} of these ${wrong} rollbacks concern more than one owner`);
console.log(`break-even: if a rollback costs more than ${(touches / wrong).toFixed(2)} human ` +
  `touches, the current boundary wins`);
console.log("probability sensitivity (expected value):");
for (const p of [0.1, 0.15, 0.2]) {
  const expWrong = humanSteps.reduce((t, a) => t + N * a.frequency * (1 - (1 - p) ** (a.missing ?? 1)), 0);
  const expTouches = humanSteps.reduce((t, a) => t + N * a.frequency, 0);
  console.log(`  p=${p.toFixed(2)} -> expected wrong ${expWrong.toFixed(1)}, ` +
    `break-even ${(expTouches / expWrong).toFixed(2)} touches`);
}
```

```
step                                              actor          class           reason
------------------------------------------------------------------------------------------------------
member scans card                                 kiosk          automatic       -
identity is verified                              identity       automatic       -
membership status is queried                      membership     automatic       -
unpaid fee is checked                             billing        automatic       -
accrued fee is collected at the counter           counter/shelf  non-system      happens outside any system
material barcode is scanned                       kiosk          automatic       -
copy status is queried                            catalog        automatic       -
transfer is opened for a copy at another branch   branch-local   human-decision  2 information item(s) in no data asset
material's damage degree is recorded              loan           human-decision  1 information item(s) in no data asset
loan period is calculated                         loan           automatic       -
researcher extension is granted                   loan           human-decision  2 information item(s) in no data asset
debt in the legacy record is queried              loan           human-decision  data with no writer: legacy-record
loan record is written                            loan           automatic       -
copy status is updated                            loan           automatic       -
security tag is deactivated                       counter/shelf  non-system      happens outside any system
overdue notification is scheduled                 loan           automatic       -

16 steps: 10 automatic, 4 human decision, 2 non-system
longest unbroken automatic run: 4 steps
handoffs: 10, 9 of which change owner; the process passes through 8 actors and 5 owners

200 loan transactions, seed 90210, wrong-decision probability per item 0.15
boundary          human touches   wrong decisions  rolled-back steps  fix writes
------------------------------------------------------------------------------------
current           62              0                0                  0
forced            0               10               30                 27

the forced boundary avoids 62 human touches, and produces 10 wrong decisions in exchange
8 of these 10 rollbacks concern more than one owner
break-even: if a rollback costs more than 6.20 human touches, the current boundary wins
probability sensitivity (expected value):
  p=0.10 -> expected wrong 9.1, break-even 6.83 touches
  p=0.15 -> expected wrong 13.4, break-even 4.63 touches
  p=0.20 -> expected wrong 17.5, break-even 3.54 touches
```

## Where the Boundary Runs

Ten of the sixteen steps are automatic, four require human judgment, two are outside the system.
These three numbers alone give the automation rate but not the boundary's **location**. The number
that gives the location is the length of the longest unbroken automatic run: four steps. The
process runs four steps automatically, then falls to the counter; two more steps run
automatically, then it snags on two human decisions. The value of automation is not in the step
count but in the length of the unbroken run — every break means a wait, a handoff, and starting
over.

At enterprise scale, the number that matters is the handoff. Across sixteen steps the actor
changes ten times, and in nine of those ten changes **the owner changes too**. The process passes
through eight actors and five separate owners. A process's enterprise cost is read from here:
technically a sixteen-step flow, organizationally nine boundary crossings.

The reasons behind the four steps requiring human judgment are not the same. In three of them, the
information is in no data asset. The fourth is different: querying the debt in the legacy record
rests on a data asset, but no system writes that data. Ownerless data comes back inside the process
as a human decision — a gap in enterprise architecture turns into a staff step in the process.

## The Cost of Forcing the Boundary

The second table runs the same two hundred loan transactions through two boundaries. Under the
**current boundary**, four steps are left to staff; across two hundred transactions these steps
occur 62 times and spend 62 human touches. Under the **forced boundary**, all four are automated;
human touches drop to zero, and wrong decisions begin in exchange.

With the generator seeded at 90210, this run produced 10 wrong decisions; since the expected value
is 13.4, the number depends on the run and changes if the seed changes. Ten wrong decisions roll
back 30 steps, and the fix requires a system write 27 times. The number that matters at enterprise
scale is the last one: **eight of the ten rollbacks** concern more than one owner. The cost of a
wrongly automated step is not fixing a single screen, it is two or three separate budget owners
reconciling the same record.

The decision is read from here: if reconciling a rollback costs more than 6.20 human touches, the
current boundary wins. This number is sensitive to probability — when the probability of a wrong
decision per missing information item is 0.10, the break-even rises to 6.83 touches; at 0.20 it
falls to 3.54. Forcing the automation boundary is not a matter of courage, it is the comparison of
these two numbers: touches avoided and rollbacks produced.

## Summary

- Three fields of a process step are measurable: actor, input set, output; the notation's symbol
  set is secondary next to these fields.
- The automation boundary is derived from a rule: a step is automatic only if all its inputs are
  in a data asset that has a writer and no information item falls outside it.
- In the model process, 10 of 16 steps are automatic, 4 require human judgment, 2 are outside the
  system; the longest unbroken automatic run is 4 steps.
- The process passes through 8 actors and 5 owners; the owner also changes in 9 of the 10
  handoffs.
- When the boundary is forced, 62 human touches are avoided; in exchange this run produces 10
  wrong decisions, 30 rolled-back steps, and 27 fix writes; 8 of the rollbacks concern more than
  one owner, and the break-even point is 6.20 touches.

## Next Step

This lesson opened up a single process for a single capability and counted which systems that
process passes through. The enterprise has thirteen capabilities, and a similar chain stands
behind each one. When a capability changes — the loan-period rule is renewed, a membership
condition changes — which systems will be touched, what data those systems write, and who reads
that data is not known unless it is traced one by one. The next lesson builds a traceability chain
between capability, system, and data; it counts the number of systems touched when a capability
changes and the points where the chain breaks.
