System Flow
A system flow maps what the software does in response to a user action: the events fired, validations run, jobs queued, APIs called, records written, notifications sent, logs kept. The actor is the system, not the person. Where a user flow (User Flow) asks "what does the user do next?", a system flow asks "what does the system do next — and how long does it take, and what can fail?" Distinct from a data flow (Data Flow), which tracks where information moves and lives; a system flow tracks actions and events in time. They overlap; draw whichever answers your question, or both. Near-synonyms: backend flow, technical flow, sequence diagram (the UML formalization of the same idea).
Why designers draw them
You cannot design honest UI without knowing what it depends on:
- Latency: is this step 50 ms or 50 seconds? That decides whether you need optimistic UI, a spinner, a progress bar, or "we'll email you" (Feedback, Loading, Errors & Recovery).
- Async states: anything queued or backgrounded means the user can navigate away mid-work — so every async step forces UI states: in-progress, done-while-you-were-away, failed-while-you-were-away (State Flow).
- Failure sources: every system step is something that can break, and each break needs a user-facing story — retry? partial result? support escalation? (Error Flow).
- Notifications: system events are what notifications are made of; mapping the events tells you what's worth telling the user (Notification Flows).
The recurring design failure: UI mocked as if the system were instant and infallible, then "temporarily" wrapped in a spinner when reality arrives. Drawing the system flow first makes waiting and failure first-class design material instead of patchwork.
What it answers
What events does this user action trigger? Which steps are synchronous (user waits) vs. asynchronous (user can leave)? What are realistic durations? What breaks, and what does the user see when it does? What's logged and auditable? What happens on retry — is the operation safe to run twice?
Example — file upload
[User clicks Upload] USER SEES: picker, then
→ Event: upload started progress bar (real %,
→ Transfer to server (1s–2min, not fake — transfer
size/network dependent) progress is measurable)
└── connection drops → auto-retry ×3
└── still failing → "Upload failed — Retry" (file
kept locally; user's work never lost)
→ Validate (type, size, malware scan) USER SEES: brief "checking…"
└── invalid → reject with SPECIFIC reason ("PDF over 50 MB")
— validation copy is designed, not a server string
→ Store file + write DB record USER SEES: nothing (fast)
└── storage fails → error + retry; no half-saved ghosts
→ Queue processing job USER SEES: "Processing —
(async — seconds to hours we'll notify you." User
depending on queue depth) may leave. Item shows
'processing' badge in list.
└── job fails/times out → item flagged "failed" in list +
notification with retry action — NOT silent
→ Generate preview USER SEES: thumbnail appears
└── preview fails but file is fine → generic icon, file
still usable (partial success is a state — design it)
→ Notify user + write audit log USER SEES: toast if present;
push/email if they left
The two-column form is the discipline: every system step is annotated with what the user sees during it. Any system step with a blank right column is a black hole where users refresh, resubmit, and file tickets.
Working with developers
A system flow is the best collaboration artifact designer↔engineer: concrete enough for engineers to correct ("actually the scan is async, up to a minute"), plain enough for designers to own. Draw your best guess and ask engineering to redline it — the corrections are the design requirements. Ask specifically: Realistic p95 timings, not demo timings? Which steps can fail independently? Is retry safe (idempotent), or does clicking twice double-charge? What's the event/webhook when it finishes — can the UI update in real time or must it poll? Cross-view: Service Blueprint draws this same backstage machinery anchored to the customer journey.
Common mistakes
- Assuming instant: no design for the 30-second version of a 2-second step (queues back up; networks degrade).
- Silent async failure — job dies, UI says "processing" forever. Every queued job needs a timeout and a user-visible failure state.
- No partial-success states (file stored, preview failed).
- Fake progress bars on unmeasurable steps — show progress only where you can measure it; otherwise show stage names.
- Designing only the tab that stayed open: async completion must also surface for users who left (badge, list state, notification).
- Losing user work on failure — the system may fail; the user's input must survive.
Checklist
- Every system step annotated with what the user sees during it — no blank columns.
- Sync vs. async marked per step, with realistic (p95) durations from engineering, not demo timings.
- Every step has a failure branch with a user-facing outcome (Error Flow); no silent failures, no eternal "processing."
- Async steps have UI states for done/failed while away (State Flow) and a notification decision (Notification Flows).
- Partial-success states identified and designed.
- Retry semantics confirmed (idempotent or guarded).
- User input survives every failure path.
- Reviewed and redlined by engineering.
Sources
- Object Management Group — UML specification (omg.org/spec/UML) — sequence and activity diagrams, the formal notations for system-behavior-over-time that system flows simplify.
- Harel, D. (1987). "Statecharts: a visual formalism for complex systems." Science of Computer Programming, 8(3) — the formal basis for the async/failure state thinking (see State Flow).
- Nielsen Norman Group — response-time and progress-feedback guidance (nngroup.com) — why step duration dictates feedback pattern; see also Feedback, Loading, Errors & Recovery.