Workflows
09 – Workflows
Target: 3–4 years experienced AEM Developer Syllabus point covered (19, first half): "Scheduler/workflow examples. Say you haven't done it but you know about it." Project domain: a global energy technology company's marketing site.
Before we start — about that note in your syllabus
Your syllabus point 19 says something the others don't:
"scheduler/workflow ke examples. bol dena kiya nai par pata hai " — "say you haven't done it, but you know about it."
That is a note the candidate wrote to themselves about how to answer, not about what to learn. And it is genuinely good instinct, so this file is built to support it properly.
Why it's the right instinct. Workflows are a topic where plenty of AEM developers have real gaps. Many projects use the out-of-the-box workflows and never write a custom process step. Claiming deep hands-on experience you don't have is dangerous here, because the follow-ups get specific fast — "where is the model stored?", "what does your process step's execute signature look like?", "how did you get a resource resolver inside it?" — and vague answers to those are worse than a clean admission.
But "I haven't done it" on its own scores zero. The version that scores well has three parts:
- Say what you have seen. Almost everyone has used workflows even if they haven't built one — approving a page, watching DAM Update Asset run, seeing items in the Inbox.
- Demonstrate you understand the model. Structure, storage, step types, how a custom step is written.
- Say how you'd approach it. Concretely enough that it's obvious you could.
Done that way, an honest answer often lands better than an inflated one, because interviewers can tell the difference and they are actively watching for it. Section 6.1 is that answer written out.
One more thing worth knowing before you decide how to pitch it. On AEM as a Cloud Service, asset processing has moved off workflows to Asset Compute microservices, and long-running workflows are actively discouraged because pods get recycled. So workflows matter less on modern projects than they did on 6.5 — and saying that shows current awareness rather than a gap. Section 2.9.
1. Introduction
1.1 What is a workflow?
A workflow is a defined sequence of steps that automates a business process in AEM — including steps that require a human.
That last clause is what makes workflows distinct from everything else in AEM. A scheduler runs code on a timer. A Sling Job processes something asynchronously. Only a workflow can stop and wait for a person.
A concrete example from our domain. A product page for a high-voltage transformer cannot simply be published by whoever edited it. Technical claims have to be checked by an engineer, and regulatory statements by compliance. So:
That process has waiting, branching, accountability and an audit trail. That is what workflows are for.
1.2 When do you use a workflow — and when don't you?
This is the question interviewers actually care about, because reaching for a workflow when you don't need one is a common design mistake.
Use a workflow when:
- A human must approve or act.
- You need an audit trail — who approved what, and when.
- The process is long-running and may pause for hours or days.
- Business users need to see and manage it in a UI.
Don't use a workflow when:
- It's just time-based — that's a Scheduler.
- It's bulk async processing with no human involved — that's a Sling Job.
- It needs to happen during a request — that's a servlet or a service.
The comparison in one line, which is worth memorising:
"Scheduler is time. Job is throughput. Workflow is people and paper trail."
1.3 What you've almost certainly seen, even if you haven't built one
Worth cataloguing, because this is the honest foundation of a good answer:
DAM Update Asset — runs whenever an asset is uploaded, generating renditions and extracting metadata. On AEM 6.5 this is a workflow. If you've ever uploaded an image and watched thumbnails appear, you've watched a workflow run.
Request for Activation — when an author lacks publish rights, activating creates a workflow that sends the request to an approver's Inbox.
Translation workflows — created when you start a translation project.
Scheduled activation — publishing a page with an on-time creates a workflow that waits.
Saying this in an interview is a genuinely strong move, because it is true, it's specific, and it converts "I haven't done it" into "here's what I've actually observed."
2. Core Concepts
2.1 The five pieces
Every workflow question comes back to these. Learn them as a set.
graph TD A["LAUNCHER<br/>watches for a content event"] -->|"triggers"| B["MODEL<br/>the definition — the steps"] B -->|"creates"| C["INSTANCE<br/>one running execution"] C -->|"carries"| D["PAYLOAD<br/>the content being acted on"] C -->|"executes"| E["STEPS<br/>process · participant · split"] E -->|"human steps appear in"| F["INBOX"]
The model/instance distinction is the one to be crisp about. A model is the design; an instance is one run of it. Ten authors submitting ten pages produces one model and ten instances. That is also why /var/workflow/instances grows and needs purging — every run leaves a record.
2.2 Where everything is stored
Interviewers ask this, and the answer changed across versions — which is worth knowing.
Two things to notice:
Models moved out of /etc. In AEM 6.2 and earlier they lived at /etc/workflow/models. The repository restructuring in 6.4/6.5 moved them to /conf — the same shift that moved templates and clientlibs, from file 01. Mentioning that connection shows you understand the pattern rather than having memorised a path.
There are two copies of every model — a design copy under /conf and a runtime copy under /var. That surprises people, and it explains a real bug:
If you edit a workflow model and your change doesn't take effect, you probably didn't sync it. The editor has a Sync button that regenerates the runtime copy from the design copy. Until you do, running instances use the old definition.
That is a good detail to have, because it's the kind of thing only someone who has actually opened the workflow editor knows.
2.3 The step types
There are more than people expect. Knowing the range — even without having built each — demonstrates real familiarity.
The two that matter most:
Process Step is where developers live. It runs a Java class you wrote.
Participant Step is what makes a workflow a workflow. It assigns the item to a person or group, puts it in their Inbox, and the instance pauses indefinitely until they act.
A distinction worth having ready: "Or Split takes one branch based on a condition; And Split runs branches in parallel and rejoins." That's a common quick question.
2.4 Writing a custom process step
This is the code developers actually write, and the piece to be able to sketch even if you haven't shipped one.
Four things to be able to explain:
service = WorkflowProcess.class — this is an OSGi service, so everything from file 06 applies. It's registered under the WorkflowProcess interface, which is how the workflow engine finds it.
process.label — this is what appears in the dropdown when someone configures a Process Step in the workflow editor. Without it, your step is unlabelled and effectively unfindable. This is the property people forget.
The execute signature takes three things:
Getting the payload — the content the workflow is acting on:
Getting a ResourceResolver — and this is a genuinely good detail:
That resolver is the workflow session's, so do not close it — the same rule as the request's resolver in file 07. If you need different permissions, open your own service-user resolver in try-with-resources.
Reading step arguments:
PROCESS_ARGS is the free-text argument field on the Process Step's configuration dialog — how one Java class is reused across several steps with different settings.
2.5 Workflow Launchers
A launcher is a rule: "when this happens in the repository, start this workflow."
What you configure:
Two things that cause real production problems, and both make good scenario answers:
Too broad a path. A launcher on /content with node type cq:PageContent fires on every page edit across the entire site. On a large site that's thousands of workflow instances an hour, and /var/workflow/instances fills the disk. Scope the path as narrowly as possible.
No run mode restriction. A launcher with no run mode set runs on publish too. An approval workflow firing on the publish tier is both pointless and a performance problem — publish should be serving pages, not running business processes. Almost every launcher should be restricted to author.
2.6 Transient workflows — the performance option
A detail that separates people who have operated AEM from people who have only read about it.
The problem. Every workflow instance creates nodes under /var/workflow/instances — the history, the work items, the metadata. For an approval workflow running a few times a day, that's fine and you want the record. For a workflow that runs on every asset upload, when you're ingesting fifty thousand product images, it's a serious repository problem.
The solution. A model can be marked transient. A transient workflow doesn't persist instance nodes at all. It runs, does its work, and leaves no trace.
DAM Update Asset is transient by default in newer AEM versions, for exactly this reason.
The trade-off to state: you give up the audit trail and the ability to see or restart the instance. So transient is right for automated, high-volume, low-stakes processing — and wrong for anything anyone might need to prove happened.
2.7 The out-of-the-box workflows
Being able to name several shows familiarity even without custom development:
2.8 Workflow versus Scheduler versus Sling Job
This is the comparison your syllabus is really asking about, since point 19 groups schedulers and workflows together. Full detail on the other two is file 10.
The three-example answer interviewers like:
- "Send a report every night at 2am" → Scheduler. Time-based, no human, no record needed.
- "Process 100,000 assets" → Sling Jobs. Needs guaranteed execution and cluster awareness, but no human.
- "Legal must approve before publish" → Workflow. A human step, an audit trail, and business users need to see it.
2.9 Workflows on AEM as a Cloud Service — what changed
This matters, and raising it unprompted turns a knowledge gap into current awareness.
Asset processing moved off workflows entirely. On 6.5, DAM Update Asset ran on the AEM instance — CPU-heavy image and video processing competing with authors for resources. On Cloud Service that moved to Asset Compute microservices, configured through Processing Profiles rather than a workflow model.
Long-running workflows are discouraged. Publish and author pods are recycled — during deployment, during scaling, or if a pod becomes unhealthy. A workflow paused mid-execution has to survive that, which is fine for a persisted approval workflow waiting on a person, but bad for a step doing hours of continuous processing.
Maintenance is automated. Adobe handles workflow purging, which on 6.5 was a task you had to configure and monitor.
What still applies: custom approval and business-process workflows work exactly as before. It's specifically the asset processing use case that moved.
Why this is worth saying:
"It's worth noting that workflows matter less on Cloud Service than they did on 6.5. Asset processing — which was the highest-volume workflow use case — moved off to Asset Compute microservices and Processing Profiles. And long-running workflows are discouraged because pods get recycled. Custom approval workflows are still workflows, but the heavy automated processing that used to be a workflow problem is now a different mechanism."
That reframes "I haven't built many workflows" as "our platform doesn't need as many," which is both honest and current.
3. Internal Working
3.1 The lifecycle of a workflow instance
sequenceDiagram participant A as Author participant L as Launcher participant E as Workflow Engine participant I as Instance (/var) participant P as Process Step participant H as Human (Inbox) A->>L: edits and saves a page L->>L: does the event match?<br/>path · node type · run mode L->>E: start the model E->>I: create the instance node E->>P: execute the first Process Step P->>P: run Java, read the payload P-->>E: done, advance E->>H: Participant Step → into the Inbox Note over E,H: The instance now WAITS.<br/>Possibly for days. H-->>E: approved E->>P: next step — activate the page E->>I: mark complete
Three things worth drawing out:
The launcher decides whether to start anything. Path, node type and run mode are all evaluated first — which is why a badly scoped launcher creates thousands of unwanted instances.
A Participant Step pauses indefinitely. The instance sits in /var consuming a little space until a person acts. If nobody ever does, it sits there forever — which is how workflows "pile up."
Every instance leaves a record unless the model is transient. That is the audit trail, and it is also the disk-space problem.
3.2 Why /var/workflow/instances fills the disk
A classic production scenario, and the mechanism is worth understanding.
graph TD A["Every workflow run creates<br/>instance nodes in /var"] --> B{"Is the model transient?"} B -->|Yes| C["Nothing persisted ✓"] B -->|No| D["Nodes persist AFTER completion<br/>— that's the audit trail"] D --> E{"Is the Workflow Purge<br/>maintenance task running?"} E -->|Yes| F["Old instances removed ✓"] E -->|No| G["Grows without bound<br/>→ DISK FULL"]
The key insight: completed instances are not deleted. They stay, deliberately, because they are the audit record. Something has to remove them, and that something is the Workflow Purge maintenance task.
Three things make it worse:
- A launcher scoped too broadly, creating far more instances than intended.
- Stalled instances waiting on a person who never acts — those can't be purged as completed.
- Purge configured to keep too long a history.
That combination — too-broad launcher plus no purge — is behind most "AEM disk full" incidents on 6.5, and it is a good scenario answer because it links a design mistake to an operational failure.
3.3 Workflow failures
When a Process Step throws, the instance goes into a Failure state rather than silently dying. You can see failures in the workflow console and retry or terminate them.
Which is why exception handling in a process step matters. Throwing WorkflowException puts the instance in Failures where someone can act on it. Swallowing the exception silently marks the step complete and the workflow moves on as though it succeeded — which is worse, because the process appears to have worked.
"In a process step I'd throw
WorkflowExceptionon a genuine failure rather than swallowing it, so the instance lands in the Failures queue where someone can see and retry it. Silently catching means the workflow completes as though it succeeded, and for something like a compliance approval that's a much worse outcome than a visible failure."
8. Coding Examples
8.1 A custom process step, annotated
The six things to be able to point at:
process.label is what makes the step selectable in the editor. Forgetting it is the classic first mistake.
The payload type is checked, not assumed.
The resolver comes from the workflow session and is not closed — you didn't open it.
The payload may no longer exist, because a workflow can pause for days on a human step and content changes meanwhile. That check is the kind of thing only someone thinking about long-paused instances includes.
Work-item metadata versus workflow metadata — per step versus shared across the instance.
Exceptions are thrown, not swallowed, with the reason stated.
8.2 A dynamic participant chooser
For when the assignee depends on the content.
8.3 A workflow launcher configuration
The two properties that cause production incidents are glob and runModes, and both are commented above for exactly that reason.
8.4 Testing a process step
Note the tests target the failure paths — a deleted payload, the wrong payload type. The deleted-payload case is specifically a workflow concern, because instances can pause for days and the world changes underneath them.
9. Common Mistakes
10. Best Practices
On launchers. Scope the path as narrowly as the requirement allows, always restrict run modes to author, and match on cq:PageContent for page edits. Every unnecessary instance is repository growth you'll pay for later.
On models. Assign to groups, never individuals. Design the stuck case up front — what happens when nobody acts. Use transient only where the audit trail genuinely doesn't matter.
On process steps. Throw rather than swallow, so failures are visible. Don't close the workflow session's resolver. Null-check the payload, because it may have gone. Keep steps fast, and push slow external work out to a job or an External Process Step.
On operations. Make sure Workflow Purge is configured and actually running on 6.5. Monitor the instance count as a leading indicator — it rises long before the disk fills.
On tool choice. Workflow for people and audit trails. Scheduler for time. Sling Job for throughput. Reaching for a workflow because it's familiar is how bulk processing becomes an operational problem.
11. Debugging Tips
The workflow console is the starting point: Tools → Workflow, or /libs/cq/workflow/content/console.html.
When a workflow is stuck, look at which step the instance is on:
- A Participant Step → it's waiting on a person. Check who it's assigned to, and whether that user or group still exists. An instance assigned to a departed user is the classic case.
- A Process Step → check
error.logand the Failures queue.
From the console you can terminate, retry or advance an instance.
When a workflow doesn't start at all, check the launcher: is it enabled, does the path glob actually match, is the node type right (cq:PageContent, not cq:Page), and does the run mode include this instance?
When your model edits have no effect, you didn't sync. There are two copies and the runtime one is generated from the design one.
When renditions or asset processing fail, remember which platform you're on. On 6.5 that's DAM Update Asset — a workflow, so check Instances and Failures. On Cloud Service it's Asset Compute, so check the asset's processing status and the Processing Profile instead.
That last one is worth remembering: a process step is an OSGi service, so if it has an unsatisfied @Reference, the component never activates and the step simply doesn't appear in the editor — exactly the file 06 problem in a new place.
12. Performance Optimization
Launcher scope is the highest-impact lever. An unscoped launcher can create orders of magnitude more instances than intended, and every one is repository writes and workflow-engine work.
Transient models where audit isn't needed. No instance nodes, meaningfully faster, no repository growth. This is why DAM Update Asset is transient by default.
Workflow Purge must actually be running on 6.5. Completed instances persist deliberately — something has to remove them.
Keep process steps fast. Each occupies a workflow thread. Slow external calls belong in a job or an External Process Step, and always with timeouts.
Don't use workflows for bulk. Per-instance overhead dominates when the work per item is small.
Watch the instance count as a leading indicator. It grows long before the disk fills, so it's the thing to alert on.
15. Comparison Tables
Workflow vs Scheduler vs Sling Job
Model vs Instance
Normal vs Transient
Step types
AEM 6.5 vs Cloud Service
Next topic
10-Schedulers-Jobs-and-Events — the second half of your syllabus point 19: Sling Scheduler with cron expressions, Sling Jobs and why they're the right answer for bulk processing, event handlers and observation, and the cluster problem — how you stop a scheduled task running on every node.
Topic 09 of the AEM Interview Preparation repository. Teaching style, energy-sector project domain.