Component reference
A practical guide to every building block in the component library: what it represents, where it connects, which settings you can change, and a small example.
How to read this page
Each entry starts with the component's ports — the connection points shown in the editor — and its settings. Then a use case shows the component doing its job in a small diagram. Port purposes are explained in Components & ports; the arrow styles follow the connection types.
Sources & triggers
Routing & compute
Data & state
Messaging
Control & orchestration
Boundaries & helpers
The editor is the final source for the choices available in your workspace. This page uses the same live component catalog, so its ports and settings stay aligned with the product.
Sources & triggers
Source components are where runs begin. An actor models traffic that a person or client system starts on demand; a scheduler models traffic that time starts for you.
Actor / clientTakes part in a run
Starts a bounded request and receives its explicit response.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | out | request | request | required |
| response | in | response | response | — |
| event | out | enqueue | event | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Request count | Root requests emitted for this scenario. | 1–1,000 | 1 |
| Interval (ms) | Virtual milliseconds between root requests. | 0–3,600,000 | 0 |
Use case — a shopper checks out
A shopper presses Buy in a web shop. The actor’s request port starts the journey and its response port receives the final answer — that round trip is the story most scenarios tell. Set Request count to 5 and Interval (ms) to 200 and the same actor becomes a small burst of shoppers, with each request visible throughout the run.
The event output is for things the client sends without waiting — an analytics beacon dropped onto a queue, or an event published to a topic — so you can model “tell and move on” traffic from the same actor that makes requests.
In a run you’ll see: TOKEN_EMITTED · CALL_STARTED · RESPONSE_RECEIVED · CALL_COMPLETED
Scheduler / triggerTakes part in a run
Starts bounded scheduled work by emitting tick events at a fixed virtual interval.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| tick | out | enqueue | event | required |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Tick count | Scheduled ticks emitted for this scenario. | 1–100 | 1 |
| Interval (ms) | Descriptive virtual schedule duration; a scenario may use a shorter run horizon. | 0–31,536,000,000 | 1000 |
| Start offset (ms) | Descriptive virtual schedule duration; a scenario may use a shorter run horizon. | 0–31,536,000,000 | 0 |
Use case — a nightly report job
Nothing clicks a button at 2 a.m. — a schedule does. Here the scheduler stands in for a cron job: each tick drops a job onto a queue, and a worker service builds the report. Set Tick count to 3 and Interval (ms) to 60,000 to watch three job cycles play out — including what happens when one of them fails and retries.
The tick port sends events, so it plugs into anything that consumes events: a queue’s enqueue, a service’s event input, or a topic’s publish. Ticks are bounded — the run emits exactly the count you configure, offset and spaced by virtual time — so a scheduled scenario always finishes.
In a run you’ll see: TOKEN_EMITTED · QUEUE_ENQUEUED · QUEUE_DEQUEUED
Routing & compute
These are the components that carry a request through the middle of a system: the gateway decides where traffic goes, services do the work, and transforms reshape data on the way through.
Gateway / routerTakes part in a run
Validates and routes a request through ordered rules.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request in | in | request | request | required |
| request out | out | request | request | required |
| response in | in | response | response | — |
| response out | out | response | response | — |
| error | out | terminal | response | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Route mode | How ordered routing rules choose a branch. | first-match | first-match |
Use case — a public API edge
A mobile app calls your public API. The gateway checks each request and routes it onward using its outgoing request connections as ordered rules — the connection priorities set the order, and with first-match routing the first rule that applies wins. Requests the gateway refuses leave through the error port instead, so a rejection is a visible route in the diagram, not a silent dead end.
The responses flow back through the gateway’s response in and response out ports. You never draw those return connections yourself — they’re paired automatically when you draw the forward requests — so the caller always gets an answer through the same route it called.
In a run you’ll see: ROUTE_EVALUATED · ROUTE_SELECTED · RESPONSE_SENT
Service / functionTakes part in a run
Performs bounded compute and explicit downstream calls.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request in | in | request | request | required |
| call | out | request | request | — |
| return | in | response | response | — |
| response | out | response | response | required |
| data command | out | write | command | — |
| data result | in | read | record | — |
| event | in | consume | event | — |
| ACK | out | ack | response | — |
| NACK | out | nack | response | — |
| publish event | out | enqueue | event | — |
| write record | out | write | record | — |
| publish event | out | publish | event | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Operation | Safe, provider-neutral service behavior. | pass-through | worker | pass-through |
| Duration (ms) | Illustrative virtual execution duration. | 0–3,600,000 | 10 |
Use case — a checkout service orchestrating a purchase
The service is the workhorse of most diagrams. This checkout service receives an order on request in, then uses three different kinds of ports for three different conversations: call / return to ask the auth service a question and wait, data command / data result to read the orders database, and publish event to announce the finished order without waiting for anyone.
What the service does with these connections — and in which order — is its handler: call auth, load the order, publish the event, respond. Switch Operation to worker and the same component plays the other classic service part: consuming messages from a queue through event in and reporting its verdict through ACK / NACK.
In a run you’ll see: NODE_ENTERED · CALL_STARTED · CALLER_WAITING · RESPONSE_SENT · NODE_EXITED
TransformTakes part in a run
Projects and validates bounded request or record payloads without arbitrary code.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | in | request | request | — |
| response | out | response | response | — |
| record input | in | read | record | — |
| record output | out | write | record | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Mapping | Allowlisted payload mapping for this transform. | identity | identity |
Use case — normalizing a legacy record
A profile service reads customers from a legacy database whose records don’t match what the rest of the system expects. Placing a transform between the database result and the service makes that reshaping an explicit, visible step — the payload before and after the transform shows up in the run, which is exactly where data-shape surprises like to hide.
The current mapping choice is identity — the transform validates and passes the payload through unchanged. The bounded mapping language (copy, rename, remove, construct) arrives in a later release; the component is where those mappings will live.
In a run you’ll see: SCHEMA_VALIDATED · TRANSFORM_APPLIED
Data & state
State components remember things between steps of a run. What they hold at the start comes from your scenario’s fixtures; what they hold at the end is part of the story the run tells.
Cache / key-value storeTakes part in a run
Models explicit get, set and delete operations with lazy TTL.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| lookup | in | read | command | required |
| hit | out | response | record | — |
| miss | out | response | record | — |
| write | in | write | record | — |
| written | out | ack | response | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| TTL (ms) | Virtual lifetime of a cached value. | 0–31,536,000,000 | 60000 |
| Key path | Bounded payload path used as the cache key. | text | /key |
Use case — cache-aside session lookup
A session service checks the cache before touching the database. The cache’s defining feature is that hit and miss are separate output ports, so the fast path and the slow path are two different routes you can see and follow. On a miss the service loads from the database — and the database’s result can feed the cache’s write port directly, modeling the write-back that makes the next lookup a hit.
The TTL setting gives every entry a virtual lifetime, and Key path says which part of the payload identifies the entry (like /sessionId). Preload entries through scenario fixtures to start a run with a warm cache — or leave it cold and watch the misses.
In a run you’ll see: CACHE_LOOKUP · CACHE_HIT · CACHE_MISS · CACHE_WRITE · CACHE_EXPIRED
DatabaseTakes part in a run
Reads and mutates bounded scenario fixture records.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| query | in | read | command | required |
| result | out | response | record | required |
| write | in | write | command | — |
| written | out | ack | response | — |
| record read | in | read | record | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Collection | Scenario fixture collection used by the database. | text | records |
| Operation | Bounded database operation. | get | query | insert | update | upsert | delete | get |
Use case — the orders system of record
The database holds the records your scenario cares about. An order service reads through query / result and mutates through write / written — two explicit conversations, so reads and writes are separate arrows you can trace in the run. The Operation setting picks what the component does with an arriving command: get, query, insert, update, upsert, or delete against the configured collection.
Records come from your scenario’s fixtures — you decide exactly which rows exist before the run starts, which is what makes runs repeatable. Writes during the run show up as state patches you can inspect afterwards.
In a run you’ll see: DB_READ · DB_RESULT · STATE_PATCH_APPLIED
Object storageTakes part in a run
Stores opaque objects behind explicit put, get and delete operations; tokens carry object references, never blob bytes.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| put | in | write | command | required |
| stored | out | ack | response | — |
| get | in | read | command | required |
| object | out | response | record | — |
| missing | out | response | record | — |
| delete | in | write | command | — |
| deleted | out | ack | response | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Bucket | Scenario fixture namespace holding this store's objects. | text | objects |
Use case — an image upload pipeline
An upload API stores a photo, and a thumbnailer fetches it later. Object storage models the S3-style half of that story: put stores an object and acknowledges through stored; get looks one up and branches — object when it exists, missing when it doesn’t — so the not-found path is a real route, just like a cache miss.
Tokens never carry the object’s bytes — only a reference (its key and metadata), the way real systems pass presigned URLs instead of file contents. The Bucketsetting names the fixture namespace the store reads and writes. A get is one synchronous interaction: both the object and missing returns lead to the caller's record arrival. Put and delete acknowledgements are responses instead: stored and deleted lead to the caller's response arrival.
In a run you’ll see: OBJECT_PUT · OBJECT_GET · OBJECT_MISSING · OBJECT_DELETED
Messaging
Messaging components decouple the sender from the receiver. The queue is point-to-point — one message, one consumer, with retries. The topic is broadcast — one event, every subscriber. Together they cover most of the asynchronous patterns in modern systems.
QueueTakes part in a run
Models bounded competing consumers, retries and explicit dead-letter routing.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| enqueue | in | enqueue | event | required |
| dispatch | out | request | event | required · max 1 connection |
| ACK | in | ack | response | — |
| NACK | in | nack | response | — |
| DLQ | out | terminal | event | max 1 connection |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Maximum attempts | Total delivery attempts before dead-letter routing. | 1–100 | 3 |
| Backoff (ms) | Virtual delay before a retry becomes available. | 0–31,536,000,000 | 1000 |
| Consumer slots | Maximum deterministic deliveries active at the same virtual time. | 1–100 | 1 |
Use case — a fulfilment worker with retries and a DLQ
Checkout finishes and hands fulfilment to a queue so the customer never waits on it. The queue dispatches each message to its single consumer — the worker — which reports back through ACK or NACK. A NACK sends the message back for another attempt after the configured backoff; when Maximum attempts runs out, the message takes the DLQ route instead of retrying forever.
The dispatch port accepts one connection, so the queue sends work to one consumer at a time. Watching a message bounce through MESSAGE_REQUEUED into MESSAGE_DEAD_LETTERED is one of the most instructive stories Mockflow can tell.
In a run you’ll see: QUEUE_ENQUEUED · QUEUE_AVAILABLE · QUEUE_DEQUEUED · MESSAGE_ACKED · MESSAGE_REQUEUED · MESSAGE_DEAD_LETTERED
Topic / event busTakes part in a run
Broadcasts one published event to every subscription, forking a correlated child token per subscriber with recorded lineage.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| publish | in | publish | event | required |
| deliver | out | subscribe | event | required |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Delivery mode | How published events fan out to subscriptions. | all-subscribers | all-subscribers |
Use case — fanning out an order-placed event
When an order is placed, three unrelated parts of the system care: email wants to confirm it, analytics wants to count it, loyalty wants to award points. Instead of the checkout calling all three, it publishes one event to a topic. Every connection drawn from the topic’s deliver port is a subscription, and each subscriber receives its own copy.
Each subscription receives its own copy of the event. Want a subscriber to get retries and a dead-letter path? Send that subscription to a queue first.
In a run you’ll see: TOPIC_PUBLISHED · TOKEN_FORKED · TOKEN_COMPLETED
Queue or topic? Ask who should handle the message. Exactly one consumer, with retries — queue. Everyone who subscribed, each with their own copy — topic.
Control & orchestration
Control components shape when and how work happens: pausing it, gathering parallel branches back together, and driving multi-step processes to completion.
Timer / delayTakes part in a run
Advances virtual time and resumes through an explicit output.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | in | request | request | — |
| response | out | response | response | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Duration (ms) | Virtual time advanced before the output resumes. | 0–31,536,000,000 | 1000 |
Use case — an explicit pause in the flow
Real systems are full of deliberate waits: a cool-down before a retry, a grace period before an escalation. The timer makes that wait a visible box in the diagram. A control signal arriving at start advances the run’s virtual clock by the configured duration, then continues through elapsed — nothing hidden, no implicit delays.
Because both ports carry control signals, the timer slots into control paths — it steers the flow rather than carrying business data. In the run you can watch the virtual clock jump: the wait costs virtual time, never real time.
In a run you’ll see: WAIT_STARTED · WAIT_COMPLETED
Join / aggregatorTakes part in a run
Waits for correlated branch arrivals and lets one satisfying token continue once its policy is met, completing earlier arrivals at the barrier.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| branch | in | join | event | required |
| joined | out | join | event | required · max 1 connection |
| timeout | out | terminal | event | max 1 connection |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Join policy | How many correlated branches must arrive before continuing. | all | any | count | all |
| Required count | Branches to await when the policy is Exact count. | 1–64 | 2 |
| Timeout (ms) | Virtual milliseconds before an unsatisfied group continues through timeout (0 preserves unresolved-barrier behavior). | 0–3,600,000 | 0 |
Use case — scatter-gather price quotes
A travel site asks two suppliers for a price at the same time and can only answer once both quotes are in. The fan-out half is a topic; the fan-in half is the join. Each supplier’s answer arrives at branch, and the join waits at the barrier until its policy is met — all branches, any branch, or an exact count (a quorum). Then the story continues through joined.
Mockflow keeps branches from the same request together, so two shoppers' quotes never mix. The branch that satisfies the policy is the one that continues.
One correlation limit remains: the branches of one join must share fork history — either all descending from the same fan-out, or none forked at all; mixing a forked branch with a never-forked one won’t meet. Set a positive Timeout (ms) to send an unsatisfied group through timeout. An arrival exactly at the deadline wins before the timeout fires.
In a run you’ll see: JOIN_ARRIVED · JOIN_SATISFIED · JOIN_TIMED_OUT · TOKEN_JOINED
Workflow / sagaTakes part in a run
Runs graph-derived steps sequentially as a durable saga, answering its caller once every step completes.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| start | in | request | request | required |
| step | out | request | request | required |
| step result | in | response | response | required |
| compensate | out | control | event | — |
| completed | out | response | response | required · max 1 connection |
| failed | out | terminal | response | max 1 connection |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| On step failure | How the workflow reacts when a step fails; after at least one earlier step completes, compensation dispatches every connected route without waiting for acknowledgement. | compensate | fail-fast | compensate |
Use case — an order saga, step by step
Placing an order really means several things in a row: reserve the stock, charge the payment. The workflow receives the original request on start, then drives each outgoing step connection as one sequential step — the connection priorities set the order. Each step is an ordinary synchronous call whose answer returns on step result; when the last step completes, the workflow answers its caller through completed.
Workflow steps run by the unique priority on each step request: lower values run first. MCP and editor authoring append omitted priorities, and WORKFLOW_STARTED reports the resolved order. A failed step returns through failed so the synchronous caller can close its continuation; that return edge uses the error kind. With Compensate completed steps, every compensate connection is dispatched as detached fire-and-forget work only after at least one earlier step completed. The compensation event records dispatch, not acknowledgement. A fail action ends that handler activation immediately: earlier effects remain, but later actions do not run.
In a run you’ll see: WORKFLOW_STARTED · WORKFLOW_STEP_STARTED · WORKFLOW_STEP_COMPLETED · WORKFLOW_STEP_FAILED · WORKFLOW_COMPLETED · WORKFLOW_FAILED · WORKFLOW_COMPENSATED
Boundaries & canvas helpers
The external dependency marks the edge of the world you’re modeling; groups and notes keep the picture readable without affecting behavior at all.
External dependency / terminalTakes part in a run
Models a fixed-latency dependency that answers synchronous calls with a configured success or failure outcome.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | in | request | request | — |
| response | out | response | response | — |
| event | in | terminal | event | — |
| callback request | out | request | request | — |
| callback response | in | response | response | — |
| publish event | out | publish | event | — |
| data command | out | write | command | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Mode | Fixed provider-neutral dependency outcome. | success | failure | success |
| Outcome | Named terminal outcome shown in the story. | text | completed |
| Latency (ms) | Virtual milliseconds before the configured boundary outcome. | 0–3,600,000 | 10 |
Use case — a payment provider you don’t control
Your checkout calls a payment provider, but the provider’s internals aren’t your story — only its answers are. The external dependency stands in for it: after the latency you choose, success mode replies through the matching interaction, while failure mode fails with the named outcome. Flip one setting and the same diagram tells the sad-path story — what your system does when payments are down.
Its event input also makes it a terminal sink: point a queue’s DLQ or any fire-and-forget event at it to give a story an explicit, named ending — “lands in ops audit” — instead of trailing off the edge of the diagram.
In a run you’ll see: RESPONSE_SENT · ERROR_RAISED
Diagram linkTakes part in a run
References another diagram in this workspace as a typed boundary; answers callers with a configured outcome and navigates to the linked diagram in the editor.
Ports
| Port | Direction | Role | Carries | Notes |
|---|---|---|---|---|
| request | in | request | request | required |
| response | out | response | response | — |
| error | out | terminal | control | — |
| event out | out | publish | event | — |
| event in | in | subscribe | event | — |
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Linked diagram | Opaque UUID of the target diagram in this workspace; empty means unlinked. Format is checked in pure validation, existence never is. | text | (empty) |
| Mode | Fixed provider-neutral boundary outcome for synchronous calls. | success | failure | success |
| Outcome | Named outcome attached to the response or terminal exit. | text | ok |
| Latency (ms) | Deterministic virtual-time service latency before answering. | 0–3,600,000 | 10 |
Use case — decomposing a big estate into diagrams
A real system is many diagrams, not one enormous canvas. A diagram link stands in for another diagram in the workspace: your order flow can point to Accounts without redrawing it. Select the node, choose the target diagram, then use Open to visit it. Mockflow leaves a trail back to the original diagram.
During a run, the link acts as a boundary with the success, failure, outcome, and delay you set on the link itself. It does not run the contents of the other diagram. This keeps the current story focused and predictable.
If the target is removed or you lose access to it, the node shows a broken-link state. The rest of the current diagram can still be opened, saved, and run.
In a shared view, a diagram link is shown as a labeled boundary. The viewer cannot open the linked diagram unless it was shared separately.
In a run you’ll see: RESPONSE_SENT · ERROR_RAISED
Group / boundaryVisual helper
Organizes trust zones, regions, systems or teams without executing.
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Collapsed | Hide child components while preserving the boundary. | on | off | false |
Use case — showing who owns what
A diagram that mixes two teams’ services needs boundaries. Draw a group around the payments components and label it — reviewers instantly see ownership, trust zones, or regions. Collapse a group to hide its children while you focus elsewhere; expand it when the detail matters again. Groups never execute and never change a run.
Note / legendVisual helper
Adds plain-text documentation without affecting behavior.
Settings
| Setting | What it does | Values | Default |
|---|---|---|---|
| Note text | Plain-text documentation; markup is never executed. | text | (empty) |
Use case — explaining the diagram to the next reader
Notes hold the things a diagram alone can’t say: assumptions (“charges are idempotent”), pointers (“see the retry scenario”), or a legend for your labels — as in the figure above. Note text is always plain text: it’s never executed, never rendered as markup, and never affects a run.