The workflow complexity you can't see in the diagram
When I worked at an Atlassian Partner, one of the most common gotchas I came across was the “simple workflow” problem. Take a typically simple workflow: five statuses, seven transitions, clean diagram. The kind of workflow you'd use as the poster-child for a "keep it simple" presentation.
Then you look at the workflow with a magnifying glass. One of those seven transitions carries three conditions, four validators, and six post-functions. One of the post-functions was a script nobody could really explain. Another reassigned issues to a user who is no longer a member of the team.
At a glance, the diagram showed none of that complexity.
Navigational vs Behavioural Complexity
The workflow diagram answers exactly one question: where can an issue go? That's navigational complexity, and it's the easiest to assess. Count statuses, count arrows, judge accordingly.
Behavioural complexity is a different question: what happens when an issue moves? Who's allowed to trigger it, what gets checked, what fires afterward. That's where the friction lives, and Jira gives you no immediate visual for it. On the surface, a transition carrying ten hidden rules looks identical to an empty one.
Users can learn to navigate a big workflow. What they can't do is understand why a button is missing, why a transition failed, or why a field changed on its own. Invisible friction hurts more than visible size.
What's actually attached to a transition
Three mechanisms, firing at three different moments:
Conditions run before the click. They control whether the user can see or use the transition at all. Permission checks, role restrictions, field-based logic. Here's the cruel part: when a condition blocks someone, there is no error. The button is greyed out or just absent. The user has nothing to work with, so they file a ticket that says "Jira is broken." And where does the ticket land? In your lap as the admin.
Validators run at the click. The user attempts the transition and validators judge the attempt. Required fields, resolution checks, permission verification. Validators at least fail visibly. But a validator without a custom error message produces a cryptic message, and the difference between "helpful guardrail" and "mystery" is entirely dependent on whether someone took time to write a helpful prompt.
Post-functions run after. Once the transition succeeds, they execute in sequence: set a field, change the assignee, fire an event, call a webhook, trigger additional automation. Users don't know they exist. When someone says "Jira changed my ticket by itself," a post-function did it.
So, user thinks they move their ticket, but in reality, one transition = three potentially hidden results.
The post-function risk ladder
Counting post-functions tells you little. What they do is what matters:
A set-field post-function is predictable and usually intentional. A notification is visible but may contribute to alert fatigue. An assignee change is an ownership decision the user didn't make but people notice. A webhook has its effects in another system entirely, so when that system changes, Jira doesn’t give you any feedback. An automation trigger can cascade: one transition fires a rule that edits ten issues that trigger further rules. And a script is arbitrary code, capable of many actions, including those its author no longer remembers writing.
One script post-function outweighs five set-field ones. Audit accordingly.
Auditing without losing a week
Manual route: open the workflow in edit view (not the diagram) and inventory each transition. Atlassian's advanced workflow configuration docs explain what each rule type can do. Keep in mind that the manual approach doesn't scale well.
API route: everything is exposed. GET /rest/api/3/workflow/search?expand=transitions returns every transition with its conditions, validators, and post-functions (actions in the payload), each carrying a ruleKey. System rules read like system:update-field or system:change-assignee. App rules arrive as connect:remote-workflow-function with an appKey identifying the app responsible. One afternoon of scripting gets you a behavioral inventory of every workflow in the instance. Reference: workflow search API.
Either way, what you're hunting for:
Overloaded transitions. Measure load per transition, never per workflow. Averaging across the workflow hides the one transition making everyone’s life harder.
Ordering dependencies. If post-function two reads a field that post-function one sets, maintaining that order is key. Reordering during a well-intentioned cleanup is an easy way to create a bug that rears its head again in three months.
External pointers. Webhooks, automation triggers, app functions. They break silently when the target changes. The breakage never gets connected back to the workflow because it happens in a different tool.
Orphaned app rules. Uninstalled apps and expired trials can leave dead rules behind. Some fail silently on every single transition.
The one-question test
For every transition, ask: if this blocks someone or does something surprising, would they understand why?
If the answer is no, that transition is generating friction for users and support tickets for you. Undocumented conditions, validators without error messages, and invisible post-functions are exactly where an admin’s time goes to die.
Tidy diagram, complex transitions. That’s the kind of config that eats your time.
What's the most complex workflow you've inherited?