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.

Note

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

PortDirectionRoleCarriesNotes
requestoutrequestrequestrequired
responseinresponseresponse
eventoutenqueueevent

Settings

SettingWhat it doesValuesDefault
Request countRoot requests emitted for this scenario.1–1,0001
Interval (ms)Virtual milliseconds between root requests.0–3,600,0000

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.

Web clientActor / clientStorefront APIGateway / routerrequestresponseREQ · checkoutRES
The actor starts the journey with a request and receives the response; the dotted return line is paired automatically.

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

PortDirectionRoleCarriesNotes
tickoutenqueueeventrequired

Settings

SettingWhat it doesValuesDefault
Tick countScheduled ticks emitted for this scenario.1–1001
Interval (ms)Descriptive virtual schedule duration; a scenario may use a shorter run horizon.0–31,536,000,0001000
Start offset (ms)Descriptive virtual schedule duration; a scenario may use a shorter run horizon.0–31,536,000,0000

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.

Nightly batchScheduler / triggerReport jobsQueueReport workerService / functiontickASYNCdispatch
Each scheduled tick enqueues a job; the queue dispatches it to the worker with its usual retry behavior.

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

PortDirectionRoleCarriesNotes
request ininrequestrequestrequired
request outoutrequestrequestrequired
response ininresponseresponse
response outoutresponseresponse
erroroutterminalresponse

Settings

SettingWhat it doesValuesDefault
Route modeHow ordered routing rules choose a branch.first-matchfirst-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.

Mobile appActor / clientPublic API edgeGateway / routerOrders serviceService / functionREQrouteERROR
Accepted requests are routed to the Orders service; rejected ones return to the caller along the orange error route.

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

PortDirectionRoleCarriesNotes
request ininrequestrequestrequired
calloutrequestrequest
returninresponseresponse
responseoutresponseresponserequired
data commandoutwritecommand
data resultinreadrecord
eventinconsumeevent
ACKoutackresponse
NACKoutnackresponse
publish eventoutenqueueevent
write recordoutwriterecord
publish eventoutpublishevent

Settings

SettingWhat it doesValuesDefault
OperationSafe, provider-neutral service behavior.pass-through | workerpass-through
Duration (ms)Illustrative virtual execution duration.0–3,600,00010

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.

API gatewayGateway / routerCheckoutService / functionAuth serviceService / functionOrders DBDatabaseorder-eventsTopic / event busREQcallDATAASYNC
One service, three kinds of conversation: a synchronous call, a data access, and a fire-and-forget event.

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

PortDirectionRoleCarriesNotes
requestinrequestrequest
responseoutresponseresponse
record inputinreadrecord
record outputoutwriterecord

Settings

SettingWhat it doesValuesDefault
MappingAllowlisted payload mapping for this transform.identityidentity

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.

Legacy customersDatabaseNormalize recordTransformProfile serviceService / functionresultDATADATA
Records flow from the database through the transform to the service — every hop a data-access connection you can inspect.
Note

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

PortDirectionRoleCarriesNotes
lookupinreadcommandrequired
hitoutresponserecord
missoutresponserecord
writeinwriterecord
writtenoutackresponse

Settings

SettingWhat it doesValuesDefault
TTL (ms)Virtual lifetime of a cached value.0–31,536,000,00060000
Key pathBounded 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.

Session serviceService / functionSession cacheCache / key-valueSessions DBDatabasewritelookuphitmissquery on missresultwrite back
Cache-aside: lookup first; on a miss, load from the database and write the result back into the cache.

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

PortDirectionRoleCarriesNotes
queryinreadcommandrequired
resultoutresponserecordrequired
writeinwritecommand
writtenoutackresponse
record readinreadrecord

Settings

SettingWhat it doesValuesDefault
CollectionScenario fixture collection used by the database.textrecords
OperationBounded database operation.get | query | insert | update | upsert | deleteget

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.

Order serviceService / functionOrders DBDatabaseDATA · queryresult
A read conversation: the service sends a query command and receives the matching record.

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

PortDirectionRoleCarriesNotes
putinwritecommandrequired
storedoutackresponse
getinreadcommandrequired
objectoutresponserecord
missingoutresponserecord
deleteinwritecommand
deletedoutackresponse

Settings

SettingWhat it doesValuesDefault
BucketScenario fixture namespace holding this store's objects.textobjects

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.

Upload APIService / functionMedia bucketObject storageThumbnailerService / functionputstoredgetobjectmissing
The upload service puts an object; the thumbnailer gets it back — or takes the missing route if it isn't there.
Note

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

PortDirectionRoleCarriesNotes
enqueueinenqueueeventrequired
dispatchoutrequesteventrequired · max 1 connection
ACKinackresponse
NACKinnackresponse
DLQoutterminaleventmax 1 connection

Settings

SettingWhat it doesValuesDefault
Maximum attemptsTotal delivery attempts before dead-letter routing.1–1003
Backoff (ms)Virtual delay before a retry becomes available.0–31,536,000,0001000
Consumer slotsMaximum deterministic deliveries active at the same virtual time.1–1001

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.

CheckoutService / functionFulfilment queueQueueFulfilment workerService / functionOps auditExternal / terminalenqueuedispatchACK / NACKDLQASYNCERROR
Enqueue, dispatch, verdict: NACKed messages retry with backoff until attempts run out, then dead-letter to the audit sink.

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

PortDirectionRoleCarriesNotes
publishinpublisheventrequired
deliveroutsubscribeeventrequired

Settings

SettingWhat it doesValuesDefault
Delivery modeHow published events fan out to subscriptions.all-subscribersall-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.

CheckoutService / functionorder-placedTopic / event busEmail serviceService / functionAnalytics intakeQueueLoyalty serviceService / functionpublishdeliverASYNCPUBSUB
One published event, three subscriptions: each fine-dotted connection 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

Tip

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

PortDirectionRoleCarriesNotes
requestinrequestrequest
responseoutresponseresponse

Settings

SettingWhat it doesValuesDefault
Duration (ms)Virtual time advanced before the output resumes.0–31,536,000,0001000

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.

Cool-down 5sTimer / delaystartelapsedCTRLvirtual time advances by Duration (ms) between start and elapsed
The timer's two ports both carry control signals: start comes in, and elapsed continues once the virtual duration has passed.

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

PortDirectionRoleCarriesNotes
branchinjoineventrequired
joinedoutjoineventrequired · max 1 connection
timeoutoutterminaleventmax 1 connection

Settings

SettingWhat it doesValuesDefault
Join policyHow many correlated branches must arrive before continuing.all | any | countall
Required countBranches to await when the policy is Exact count.1–642
Timeout (ms)Virtual milliseconds before an unsatisfied group continues through timeout (0 preserves unresolved-barrier behavior).0–3,600,0000

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.

quote-requestTopic / event busSupplier AService / functionSupplier BService / functionBoth quotes inJoin / aggregatordeliverbranchjoined
Two branches fan out through a topic and meet again at the join; with policy “all”, the joined output fires once both have arrived.

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.

Note

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

PortDirectionRoleCarriesNotes
startinrequestrequestrequired
stepoutrequestrequestrequired
step resultinresponseresponserequired
compensateoutcontrolevent
completedoutresponseresponserequired · max 1 connection
failedoutterminalresponsemax 1 connection

Settings

SettingWhat it doesValuesDefault
On step failureHow 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-fastcompensate

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.

StorefrontActor / clientOrder sagaWorkflow / sagaReserve stockService / functionCharge paymentService / functionstartstepstep resultREQstep 1step 2completed
One workflow, two steps: each step connection is called in order, and the caller gets its answer when the last one finishes.
Note

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

PortDirectionRoleCarriesNotes
requestinrequestrequest
responseoutresponseresponse
eventinterminalevent
callback requestoutrequestrequest
callback responseinresponseresponse
publish eventoutpublishevent
data commandoutwritecommand

Settings

SettingWhat it doesValuesDefault
ModeFixed provider-neutral dependency outcome.success | failuresuccess
OutcomeNamed terminal outcome shown in the story.textcompleted
Latency (ms)Virtual milliseconds before the configured boundary outcome.0–3,600,00010

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.

CheckoutService / functionPayment providerExternal / terminalREQ · chargeRES · mode decides
The external dependency answers with exactly what you configured — a fixed success or a named failure.

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

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

PortDirectionRoleCarriesNotes
requestinrequestrequestrequired
responseoutresponseresponse
erroroutterminalcontrol
event outoutpublishevent
event ininsubscribeevent

Settings

SettingWhat it doesValuesDefault
Linked diagramOpaque UUID of the target diagram in this workspace; empty means unlinked. Format is checked in pure validation, existence never is.text(empty)
ModeFixed provider-neutral boundary outcome for synchronous calls.success | failuresuccess
OutcomeNamed outcome attached to the response or terminal exit.textok
Latency (ms)Deterministic virtual-time service latency before answering.0–3,600,00010

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.

Order serviceService / functionAccountsDiagram link / boundaryREQ · open accountRES · mode decides
A diagram link points to the Accounts diagram; Open visits it and offers a trail back.

In a run you’ll see: RESPONSE_SENT · ERROR_RAISED

Group / boundaryVisual helper

Organizes trust zones, regions, systems or teams without executing.

Settings

SettingWhat it doesValuesDefault
CollapsedHide child components while preserving the boundary.on | offfalse

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.

Payments teamCharge serviceService / functionLedger DBDatabaseNote / legendCharges are idempotent;retries reuse the originalcharge id.
A group boundary around the payments components, with a note explaining the diagram — neither affects the run.

Note / legendVisual helper

Adds plain-text documentation without affecting behavior.

Settings

SettingWhat it doesValuesDefault
Note textPlain-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.