A reliable Microsoft 365 joiner–mover–leaver automation starts with one controlled identity record, explicit approvals and reversible changes. The automation should translate an HR or service-desk event into account, group, licence and shared-resource actions while preserving who requested each change, who approved it, what ran and what failed.
This guide is for administrators building that workflow. It focuses on implementation controls rather than the management checklist: event design, state transitions, idempotency, rollback, evidence and exceptions.
Model the lifecycle as events, not tickets
A ticket is useful to people, but it is a weak automation trigger. Free-text fields vary, updates arrive out of order and a reopened ticket can run the same action twice. Instead, translate each request into a structured lifecycle event.
A practical event needs at least:
- event_id: a unique, immutable identifier used for deduplication;
- event_type: joiner, mover, leaver, cancellation or correction;
- person_key: the HR or directory identifier, not merely a display name;
- effective_at: the approved date and time, with timezone;
- requested_state: department, role profile, manager, location and employment status;
- approval_state: pending, approved, rejected, expired or revoked;
- source_version: a sequence number or updated timestamp;
- correlation_id: a value carried into every downstream log entry.
Keep the raw source event and the normalised event. The first helps investigation; the second gives the workflow a stable contract.
Build a state machine before building the flow
Do not let an automation jump directly from “request received” to “completed”. Use explicit states such as received, validated, awaiting_approval, scheduled, executing, partially_completed, completed, rolled_back and needs_operator.
Each transition should have a guard condition. For example, awaiting_approval can move to scheduled only when the required approver has accepted the exact requested state. If the request changes after approval, invalidate the approval and return it to review.
This matters for movers. A department change may alter several entitlements at once, and an old approval should not silently cover a newly added finance group or shared mailbox.
Separate policy calculation from Microsoft 365 execution
Use one component to calculate desired access and another to apply it. The policy component should accept the normalised person record and return a change plan:
The executor then applies only this approved plan through Microsoft Graph, Entra ID tooling or a controlled orchestration layer such as n8n. This separation lets you test entitlement logic without changing a tenant and review the plan before execution.
Prefer role profiles over long lists embedded in workflows. A role profile can map “Sales Executive, Singapore” to approved groups, licences and resources. Version the profile so an audit can show which policy produced a change.
Handle joiners as staged provisioning
A joiner flow should validate the person key, name, manager, start time and role profile before creating anything. Check for an existing account using immutable identifiers rather than assuming a matching name means the same person.
Then stage actions in a deliberate order:
- Create or enable the identity with the approved naming rule.
- Apply baseline security and authentication-registration requirements.
- Add role-based groups.
- Assign the required licence only after prerequisites are present.
- Grant shared mailboxes, Teams, SharePoint sites or other resources through groups where practical.
- Record the resulting object IDs and actual state.
- Notify only the authorised recipients, without sending reusable credentials through insecure channels.
Account creation can complete before every cloud service is ready. Treat propagation delays as a retryable condition, not immediate proof of failure. Use bounded retries with backoff and a final operator handoff.
Calculate mover changes as a diff
A mover is not a second joiner. Read the current directory state, calculate the target state and produce a diff. Classify each line as add, retain, remove or manual review.
Removals deserve the same attention as additions. If the old role granted a finance site, privileged group or shared mailbox, leaving it in place creates access accumulation. However, do not remove every non-target group blindly: some memberships may be individually approved, project-based or managed by another system.
Maintain an ownership field for entitlements. The automation can safely remove role-owned access when the role changes, while preserving separately approved access until its owner reviews it.
For sensitive changes, execute additions and removals as separate controlled stages. That makes partial completion visible and provides a clearer recovery path if one API operation fails.
Design leaver flows around timing and evidence
Leaver events need an effective time that is distinct from the request time. At the approved point, the flow may disable sign-in, revoke active sessions, remove group access, handle licences and trigger resource handover tasks. Exact actions depend on the organisation’s approved process and technical setup.
Shared data, mailbox access, file ownership and retention should not be decided inside a generic script. Convert them into explicit tasks with named owners and expiry dates. Where an action cannot be automated safely, mark it as manual and keep it in the same evidence trail.
A cancellation or changed departure time must supersede the earlier event. Before execution, re-read the latest event version. This prevents a queued leaver job from disabling an account after HR has cancelled the request.
Make every operation idempotent
Retries are normal. A flow may time out after Microsoft 365 accepted a change but before the orchestrator stored the response. Every step should therefore compare desired and actual state before writing.
- If the user already belongs to the target group, record “already compliant” rather than adding again.
- If the intended licence is already assigned, skip the write.
- If an event ID is already completed for the same source version, do not replay it.
- If a newer version exists, stop the stale run.
Store step-level status under the event ID. Restart from the first incomplete safe step instead of replaying the entire lifecycle.
Use compensating actions, not imaginary transactions
Microsoft 365 changes across identities, groups, licences and resources are not one database transaction. You cannot assume all changes will commit or all will roll back automatically.
Define a compensating action for each reversible step. If a mover flow adds a target-role group but fails while removing old access, the recovery may remove the newly added group or leave it in place while escalating, depending on the approved risk rule. Capture the chosen behaviour in the change plan.
Some actions are not safely reversible. Deleting an object, changing ownership or releasing a licence may have downstream effects. Prefer disable, quarantine or delayed cleanup stages when the business process allows them. Require an operator for destructive recovery.
Keep approval state inside the execution record
An email saying “approved” is difficult for automation to validate. Store the approver identity, timestamp, approved event version, scope and any conditions in a system the workflow can query. Reject self-approval where separation of duties requires another person.
At execution time, verify that approval is still valid, the effective time has arrived and the source record has not changed. If any check fails, stop before writing to Microsoft 365.
Capture audit evidence that answers useful questions
A useful evidence record should answer: what was requested, what policy calculated, who approved it, what the workflow attempted, what Microsoft 365 returned, and what state was verified afterwards.
Capture:
- event and correlation IDs;
- source and policy versions;
- approver identity and approval time;
- planned additions and removals;
- API operation, target object ID, timestamp and outcome;
- sanitised error category and request identifier;
- post-change verification result;
- manual actions, owner and completion evidence.
Do not dump access tokens, passwords or unnecessary personal data into logs. Restrict evidence access and set retention according to the organisation’s policy.
Route exceptions by type
“Failed” is too broad. Classify exceptions so the right response follows:
- validation: missing manager, unknown role or invalid effective time; return to requester;
- approval: missing, expired or stale approval; pause for approval;
- conflict: duplicate identity or contradictory events; require operator review;
- transient: throttling, timeout or temporary service error; retry within limits;
- permission: executor lacks a required role; stop and escalate, do not broaden permissions automatically;
- partial execution: some changes succeeded; run the documented compensation or operator path;
- policy exception: requested access falls outside the role profile; send to the entitlement owner.
Include a dead-letter queue or equivalent operator view. Every exception should show the event, current state, last safe action and allowed next steps.
Test the control system, not only the happy path
Use a non-production tenant or controlled test identities where possible. Test duplicate events, out-of-order updates, revoked approvals, propagation delays, API throttling, partial group changes, licence exhaustion, stale leaver jobs and rollback failures.
Before wider use, run in plan-only mode. Compare proposed changes with what administrators would have done. Then enable execution for a narrow role profile and keep manual approval until the logs and exception paths are proven.
A practical implementation sequence
- Define the event schema and state machine.
- Catalogue role profiles and entitlement owners.
- Build the desired-state calculator and unit tests.
- Add an approval store tied to event versions.
- Implement idempotent Microsoft 365 steps with least-privileged service access.
- Add post-change verification and structured evidence.
- Document compensation and manual exception paths.
- Run plan-only tests, then introduce execution in stages.
For the business-facing governance view, use a separate joiner–mover–leaver checklist covering ownership, approvals and review records. A contextual link should be added after the companion Sakal Network article is published.

