⏱ 20 min read
I’ve seen this mistake often enough that I don’t really treat it as a modeling problem anymore. It’s an architecture problem.
A government modernization program launches a new permit platform. The team does all the right-looking things. Discovery workshops. Swimlanes. BPMN diagrams with carefully mapped handoffs between the citizen portal, case officer, payment service, inspection team, and appeals panel. The workflow looks great. Everybody nods. Delivery begins. BPMN training
Then the awkward questions start showing up.
Why did this application get stuck after a missing-document notice was sent? Why did one rejected permit reopen after an appeal, while another required a completely new application? Why did a case stay “approved” in one system but “suspended” in another after a fraud flag? Why did the portal still allow document upload when operations said the case was closed? Why did Kafka events show a claim moving from approved back to pending evidence with no obvious legal basis?
That is usually the moment the team realizes they modeled the process flow, but the real risk was sitting somewhere else entirely: in the lifecycle behavior of the business object itself.
That distinction matters more than most people expect.
UML State Machine Diagrams are not for everything. Most teams either ignore them altogether or misuse them badly. They are not a better BPMN. They are not a more sophisticated way to list statuses from a database table. And they definitely are not something to draw just to look rigorous in front of governance boards. BPMN and UML together
But when a system has to manage strict lifecycle states, legally valid transitions, exceptions, reversals, timers, and event-driven behavior, state machines become useful very quickly. In government, that situation comes up all the time, even when programs act as if it doesn’t.
This article is about when to use them, when not to, and how to avoid the usual traps. I’m going to stay away from toy ATM examples and stick to public-sector cases, because that’s where the technique either earns its place or collapses under its own weight.
The wrong reasons teams reach for state machines
The first bad reason is simple: they want to impress people.
You can usually spot it straight away. The diagram becomes dense, formal, and almost unreadable. Every arrow is buried under notation. Composite states inside composite states. Guards everywhere. Junctions. History markers. It looks serious. It also tells almost nobody what they actually need to know.
I’ve watched architecture teams do this in large transformation programs because they wanted to signal technical depth. In practice, it usually has the opposite effect. Policy owners disengage. Delivery teams quietly ignore it. Product managers drift back to spreadsheets. The diagram survives only in architecture packs and forgotten SharePoint pages.
That is architecture theater.
The second common mistake is treating an end-to-end business process as if it were a state machine. In my experience, this is probably the biggest source of bad diagrams.
A state machine models the lifecycle of one thing. A process model describes work moving through roles, tasks, and decisions across an organization. Those ideas are related, obviously, but they are not the same thing.
“Application is under review” might be a valid state, because that state determines what is allowed next. “Officer checks attachment” is almost certainly an activity, not a state. “Send request to environmental agency” is a step. “Case assigned to team B” is a routing detail. “User is on screen 4” is not a business state, however often people try to force it into one.
I have a fairly blunt rule here: if every workflow step becomes a state, the model is probably already broken.
Another trap is confusing status codes with actual lifecycle behavior. Public-sector systems are full of status tables. I’ve seen reference lists with 40, 60, sometimes more than 100 values, many of them accumulated over years of policy changes, local workarounds, and awkward migrations. Teams often bring that list into a workshop and say, “Great, we already have the state model.”
No. At best, you have a taxonomy of labels.
A useful state machine defines allowed transitions, triggering events, guards, entry and exit actions, and exception paths. It makes invalid movement explicit. It tells you what can happen from here and what cannot. A lookup table from the database does none of that on its own. If your “state model” is just the status column with nicer formatting, it probably isn’t architecture. It is just documenting sediment.
Then there is the habit of under-modeling reversals because people want tidy diagrams.
Government systems do not move neatly from left to right. Appeals happen. Judicial orders happen. Data corrections happen. Fraud alerts happen. Missing evidence arrives after deadlines. Ministerial exceptions appear at exactly the wrong moment. A permit can be approved, challenged, conditionally constrained, and partially reopened. A claim can be suspended while still allowing evidence intake. If the diagram cannot represent that because the team wanted a clean happy path, the diagram is lying.
One more mistake, and this one matters: treating human approval as deterministic system behavior.
Not every thought process belongs in a state machine. Human judgment is often better represented in policy logic, case management, BPMN, or operating procedures. The state machine should capture the governed lifecycle of the entity, not the full psychology of the officer, reviewer, assessor, or investigator. Teams often cram all of that into one picture and then wonder why the result is unusable.
A practical rule of thumb before definitions
Before getting into notation, I usually ask six questions.
Does the thing being modeled have a meaningful lifecycle?
Do events change what actions are permitted next?
Are there strict compliance rules around valid transitions?
Do exceptions matter as much as the happy path?
Will multiple systems need a shared understanding of status and transition semantics?
And if the wrong transition happens, does it create legal, audit, financial, or service-delivery risk?
If the answer is mostly yes, a state machine is probably worth the effort.
If the answer is mostly no, don’t force it. Use BPMN for orchestration. Use an activity diagram if you just need flow logic. Use DMN or decision tables if the real problem is policy logic. Use sequence diagrams if the concern is service interaction. Use event storming or domain modeling if you are still discovering the shape of the problem.
This sounds obvious. Teams skip it all the time.
What a UML State Machine Diagram actually models
Plainly put, a state machine models the lifecycle of one thing in response to events.
That “thing” could be a permit application, a benefits claim, a citizen identity verification case, a procurement contract, or a security accreditation request. The model is centered on that entity and the way its behavior changes over time.
States are stable conditions that matter. Not temporary implementation details. Not every internal processing step. Conditions that change what the system is allowed to do.
Transitions are movements between states.
Events trigger transitions: submission received, payment confirmed, evidence requested, timer expired, appeal lodged, accreditation revoked.
Guards are conditions that must be true for the transition to occur.
Actions are what happen on the transition, or on entry or exit. Send a notification. Emit a domain event onto Kafka. Create an audit record. Trigger a workflow. Raise a task for an officer. Recalculate entitlement. Request a new IAM authorization scope. Those are actions.
Sometimes you need composite states. Sometimes choice nodes. Sometimes history states if re-entry matters. Time events matter a lot in government, because statutory waiting periods, expiry windows, and appeal deadlines are often first-class business rules rather than just technical scheduling details.
The important point is this: a good state machine is not just documentation. In a decent architecture, it shapes the domain model, the event schema, API preconditions, validation logic, automated tests, and audit design. It becomes a behavioral backbone.
That is why it is worth doing properly.
Permit application lifecycle, not permit process
Permit systems are one of the easiest places to explain the value, partly because they are so often modeled incorrectly.
Imagine a building permit platform operating across municipal and state agencies. Citizens can apply through a portal, staff can correct data through a back-office interface, assisted service centers can submit on behalf of applicants, and several external checks are involved: zoning, environmental review, payment, inspection planning.
If you model only the end-to-end process, you get plenty of boxes and handoffs. Useful, up to a point. But it still does not answer what lifecycle the application itself is in, or what is legally valid at any given moment.
Candidate states might look something like this:
- Draft
- Submitted
- Validation Failed
- Under Assessment
- Awaiting Applicant Response
- Approved
- Conditionally Approved
- Rejected
- Withdrawn
- Expired
- Appealed
- Closed
And then the events:
- submitApplication
- validationErrorDetected
- officerRequestsMoreInfo
- applicantProvidesInfo
- statutoryTimerExpired
- decisionRecorded
- appealLodged
- appealResolved
- applicantWithdraws
A simplified version might be:
Even this very simple sketch raises real architecture questions.
Is “payment pending” a state? Sometimes yes, sometimes no. If non-payment changes the allowed behavior of the application for a meaningful period, then it may deserve to be a state. If payment is simply a prerequisite checked before transition to assessment, a guard may be enough. I’ve seen both approaches work. The right answer depends on whether non-payment is operationally significant, visible across systems, and legally material.
Another useful distinction: inspection scheduling is not necessarily part of the application lifecycle. It may be a separate process, or even a separate lifecycle-bearing entity. Teams often mix the application state with the downstream inspection process and end up with impossible hybrids such as “Approved and Inspection Pending and Appeal Open.” That usually means they have collapsed multiple concerns into one model.
Appeals are where the tidy models start to fall apart. In many real permit regimes, appeal behavior is not just a side note. It changes deadlines, communication rules, document handling, and allowable actions. In one program I worked on, we ended up with either a composite state for appeal handling or, frankly better, a secondary state machine governing the appeal case itself. Trying to squeeze all appeal behavior into a flat application state model made the whole thing unreadable.
And yes, legal deadlines matter. If the statute says evidence must be supplied within 30 days or the application expires, that is not just workflow timing. It is lifecycle behavior.
The biggest pitfall in these models is overloading “Under Assessment.” I see this constantly. It becomes a catch-all for validation, routing, internal consultation, waiting on external agencies, risk review, manager sign-off, and half the unresolved ambiguity in the operating model. If one state contains ten materially different behaviors, it is too broad.
State machine or something else?
A quick way to frame it:
The short version: state machines are surgical tools. The failure mode is not just failing to use them. It is expecting them to replace everything else.
The architecture value people underestimate
In legacy government estates, lifecycle logic is rarely clean. It is scattered.
Some of it sits in COBOL batch jobs. Some in hard-coded status flags. Some in stored procedures nobody wants to touch. Some in call-center scripts. Some in spreadsheets used by operations managers. Some in IAM exceptions that quietly determine who can do what in which state. A surprising amount of it lives in human memory.
A state machine can expose that hidden operational policy.
This becomes very tangible during cloud transformation. Once you move toward APIs, event-driven integration, and service decomposition, the old fuzzy status semantics start causing real damage. One service emits claim.suspended, another assumes suspension means no evidence can be accepted, a portal still allows upload, and downstream payment continues because the payment service interprets “suspended” differently. Add Kafka, retries, out-of-order events, and asynchronous processing, and any ambiguity gets amplified.
That is why I’m fairly opinionated on this point: if you are modernizing a case-centric public service and not making lifecycle transitions explicit, you are probably just moving ambiguity into the cloud faster.
Benefits claim under fraud review
This is where things get harder, and more realistic.
Consider a social benefits platform integrating identity verification, income checks, payment services, and fraud analytics. Most claims move through normal screening and approval. Some are flagged for enhanced review.
Possible states might include:
- Received
- Eligibility Screening
- Pending Evidence
- Approved for Payment
- Suspended
- Under Fraud Review
- Partially Restricted
- Terminated
- Reinstated
- Closed
The state machine helps answer difficult questions, not decorative ones.
What events can suspend a claim?
Does “Under Fraud Review” block all downstream actions, or only payment release?
Can a claimant submit new evidence while suspended?
What exactly does reinstatement mean? Back to approved for payment, or back to screening?
What audit events need to be emitted on transition, and who needs to receive them?
Here is the design tension that usually appears. Do you build one state machine for the whole claim, or separate state machines for claim lifecycle, payment lifecycle, and investigation lifecycle?
There is no universal answer. One model is simpler to govern and easier to explain to executives. It can also turn into a monster. Separate models give you cleaner boundaries and less coupling, but now you have coordination problems and more complex reporting logic.
In my experience, one giant state machine often looks attractive in workshops and then falls apart in implementation. The payment team has different concerns from the investigation team. The claim entity itself has its own lifecycle. If you merge all three into a single canonical machine, you often end up with a model that is conceptually pure and operationally miserable.
A more realistic pattern is multiple related lifecycle models with explicit coordination events.
That is where enterprise architecture matters. Not in drawing the picture, but in deciding ownership boundaries, event contracts, and which lifecycle is authoritative for what.
How to know the diagram is becoming harmful
There is a point where a state machine stops clarifying and starts obscuring.
The warning signs are usually obvious if you are honest about them.
More than one audience exists, but no audience can actually read the diagram.
Every exception gets promoted into a new top-level state.
Transition labels become paragraphs.
The same state name means different things to policy, operations, and engineering.
The team spends an hour debating notation while still unable to answer, “What happens if evidence arrives after suspension?”
Or the biggest smell of all: the diagram is approved in architecture review and ignored in implementation.
That usually means the model was too abstract, too rigid, or too disconnected from delivery artifacts to matter. I’ve seen this in programs where the architecture team produced elegant UML while engineering implemented a completely separate set of status enums and transition rules in code, with no traceability between the two. At that point the model is not governing anything. It is just a slide. UML modeling best practices
A practical method that actually works
My approach is boring, and deliberately so.
First, pick the right entity. One lifecycle-bearing business object. Application. Claim. Permit. Contract. Accreditation request. Not “the whole service.”
Second, gather real events, not imagined ones. Pull them from legislation, operating procedures, service desk tickets, production logs, exception reports, audit findings, and incident reviews. This is where hidden transitions emerge. In practice, you learn more from a list of awkward operational exceptions than from a polished future-state process deck.
Third, name states by behavioral meaning. A good state implies what can and cannot happen. A bad state is a vague administrative bucket. TOGAF roadmap template
Fourth, separate actions from states. “Send notification” is an action. “Awaiting applicant response” may be a state. This sounds trivial. It isn’t.
Fifth, add guards only when they reduce ambiguity. Don’t turn the diagram into executable code on paper. Keep detailed policy logic where it belongs, often in DMN, rules services, or well-structured application logic.
Sixth, model exception routes early. Appeals. Withdrawals. Timer expiry. Duplicate submissions. Fraud hold. Policy override. Record correction. If you leave them until the end, the model will either get uglier than expected or stay deceptively clean and wrong.
Seventh, validate against scenarios. Walk the happy path, of course, but also late evidence, reversal after approval, cross-agency dependency failure, manual override, and asynchronous callback arriving after state expiry.
Finally, tie the model to implementation. This is where many architecture teams stop too early. The state machine should have visible links to status representation, domain events, API preconditions, workflow orchestration, test automation, and audit schema. Otherwise it is just a concept sketch.
What to keep out of the diagram
Resist diagram inflation.
Do not put UI screens in it. Or every user task. Or organization charts. Or every REST call. Or every IAM approval step. Or long formulas for eligibility calculations. Or reporting labels invented for dashboards.
The state machine needs to remain semantically durable even as channels, technologies, and teams change. If a portal redesign breaks your state model, it was never really a lifecycle model in the first place.
Security accreditation for a cloud workload
This is the example architects tend to appreciate because it is closer to their own world.
Say a government department is moving workloads to cloud under a formal security accreditation regime. There are delivery teams, security assessors, risk owners, and operations staff. The workload itself has a governed lifecycle.
Potential states:
- Draft Control Set
- Submitted for Assessment
- Evidence In Review
- Remediation Required
- Conditionally Accepted
- Accredited
- Accreditation Expired
- Revoked
- Archived
Now the value becomes more obvious.
What moves a workload from Conditionally Accepted to Accredited? Which events trigger revocation? Does expiry happen on a timer or on the absence of refreshed evidence? What controls are allowed to remain open under conditional acceptance? Which IAM roles are permitted to deploy to production in each state? Can onboarding to shared cloud services proceed before full accreditation, and under what guard conditions?
This is not just governance paperwork. It affects control automation, policy-as-code boundaries, audit evidence management, release gating, and operational risk decisions. I’ve seen teams use event-driven patterns here effectively: accreditation status changes emitted to Kafka, consumed by deployment policy services, CMDB updates, and access control workflows. But again, that only works if the lifecycle semantics are explicit.
Where state machines fit in the broader EA toolkit
They fit best as part of a set.
The domain model tells you what the entity is and what invariants matter.
The capability map tells you where lifecycle governance is operationally important.
BPMN models the surrounding process and handoffs.
The event model identifies transition-triggering events.
API specifications enforce valid operations in each state.
The data model persists current state and transition history.
Security and NFR design deal with traceability, integrity, and auditability.
That is how I’d frame them in enterprise architecture: a behavioral backbone for lifecycle-heavy domains, not the centerpiece of every architecture pack. Sparx EA guide
Implementation issues architects often miss
A few things routinely get ignored until late.
Persistence and history, for one. In government, current state is rarely enough. You usually need immutable transition history for audit, legal discoverability, complaints, and ministerial reporting. If the design stores only the latest status value, you will regret it.
Then eventing. If transition events become integration contracts, you need to deal with duplicates and out-of-order delivery. In distributed environments, the state machine cannot assume clean sequencing just because the diagram looks neat. Kafka helps with durable eventing, but it does not magically remove bad semantics. You still need idempotency, versioning, and ownership discipline.
Ownership is another one. Which service owns the lifecycle? If three systems can mutate the same state independently, the model is already unstable. Pick an authoritative owner. Others can request, react, or project, but they should not all be free to redefine the lifecycle in parallel.
Batch and timer behavior matter too. Overnight statutory expiry jobs. SLA escalations. Reminder notices. Delayed callbacks from external agencies. Reconciliation after asynchronous failure. These are not implementation footnotes. They are often core transition mechanisms.
And testing. If a state machine exists, then transition coverage should exist too. Valid transitions, invalid transitions, time-based transitions, exception regressions. This is one of the more underrated benefits of a good model: it gives QA and engineering a much sharper test structure.
Operational observability matters just as much. You want to track state aging, detect illegal transitions, identify stuck cases, and support audit reporting. If the lifecycle cannot be observed in production, the model is only half alive.
A few modeling choices that matter
Single state machine versus multiple related ones: use one when the lifecycle is genuinely cohesive. Split when subdomains need autonomy and have different rates of change.
Flat states versus composite states: composite states can help with broad phases that contain meaningful internal behavior. They can also be abused to hide complexity instead of managing it. I’ve done both, if I’m honest.
Explicit exception states versus transition outcomes: not every error needs a state. Transient failures often belong as retry logic or operational handling. Persistent business-relevant conditions usually deserve state representation.
Enumerated statuses versus derived statuses: some dashboard-friendly labels should be derived rather than persisted. Otherwise reporting demands will bloat the lifecycle with management semantics that do not belong there.
Reasons not to use UML State Machine Diagrams
Sometimes the right answer is no.
If the lifecycle is trivial and linear, skip it.
If the rules are mainly tabular rather than behavioral, use decision tables.
If stakeholders need process visibility more than object behavior, BPMN will help more.
If the team lacks the discipline to maintain the model, a polished state machine may go stale faster than a whiteboard table.
If the product changes weekly and semantics are still unstable, keep it lightweight for a while.
Honestly, a rough event-state matrix can do more good than a beautiful UML artifact in early discovery.
How I would use them in a government transformation program
I would not start by producing a formal state machine in week one.
I’d start with event and exception workshops. Real incidents, real escalations, real reversals. Then I’d model one or two high-risk lifecycle entities first, not everything. Permits. Claims. Grants. Complaints and appeals. Investigations. Accreditation processes. Areas where a wrong transition actually hurts.
I’d use the model to expose policy ambiguity and integration risk. That is usually where the value shows up first. Then I’d translate the agreed semantics into implementation rules: APIs, workflow engines, Kafka event contracts, validation logic, audit records.
And I would keep two versions if needed. A simpler published version for broad stakeholders, and a more detailed engineering working model behind it.
One more thing, based on bruising experience: review the model after the first production incidents, not just before go-live. You learn more from the first ugly edge cases than from six neat design workshops.
Final thought
UML State Machine Diagrams are most valuable when behavior, compliance, and exception handling matter more than linear process flow.
That is common in government. Permits. Benefits. Appeals. Sanctions. Accreditations. Investigations. Anywhere a case or record has a legally meaningful lifecycle.
Used well, state machines reduce ambiguity and improve implementation integrity. Used badly, they become decorative complexity.
So the real question is not, “Should we draw a state machine?”
It is this:
Where does lifecycle ambiguity create operational or legal risk, and are we willing to make that explicit?
Frequently Asked Questions
Can UML be used in Agile development?
Yes — UML and Agile are compatible when used proportionately. Component diagrams suit sprint planning, sequence diagrams clarify integration scenarios, and class diagrams align domain models. Use diagrams to resolve specific ambiguities, not to document everything upfront.
Which UML diagrams are most useful in enterprise architecture?
Component diagrams for application structure, Deployment diagrams for infrastructure topology, Sequence diagrams for runtime interactions, Class diagrams for domain models, and State Machine diagrams for lifecycle modelling.
How does UML relate to ArchiMate?
UML models internal software design. ArchiMate models enterprise-level architecture across business, application, and technology layers. Both coexist in Sparx EA with full traceability from EA views down to UML design models.