BXUP Track progress & test yourself — free
IT Support / Service Desk / Sysadmin · Playbook · Core · ~4 min read
IT SUPPORT / SERVICE DESK / SYSADMIN · PLAYBOOK · CORE

Run Bulk Operations with Dry-Run and Rollback

Bulk changes are where careers end: 400 mailboxes modified from a CSV with one bad column, and no record of the previous state. Three conventions — validate the input, dry-run the change, write the rollback file before touching anything — let you run AI-generated bulk operations against AD, Entra and M365 and still sleep.

Tier: Core · Workflow area: Scripting & automation · ~35 minutes

This playbook wraps every CSV-driven bulk operation in three mandatory layers: input validation that rejects bad data loudly, a dry-run pass whose output a human reads, and a generated rollback file capturing prior state — with AI writing the boilerplate for all three so the safety net costs minutes, not discipline.

When to use

  • Any change touching more than ~20 objects from a list: license swaps, group membership updates, attribute stamps, OU moves, mailbox settings.
  • Changes driven by someone else's spreadsheetHR's rename list, a project's migration CSV: exactly the inputs that arrive with trailing spaces, merged cells and a typo'd UPN.
  • Recurring bulk jobsmonthly license true-ups, term-date processing — where the wrapper gets written once and reused forever.

When NOT to use

  • Under ~20 objects with human review eachclicking through fifteen changes in the console with your eyes open is sometimes genuinely safer than tooling up.
  • Irreversible operations as a first resorthard mailbox deletes, permanent object removal: rollback files cannot un-delete what the platform cannot restore. Prefer disable/soft-delete stages, and treat truly irreversible steps as their own change with its own approval.
  • When source-of-truth automation existsif HR-driven lifecycle workflows (pb-28) already handle it, a manual bulk run competes with the automation; fix the workflow instead.

The recipe

  1. Generate the wrapper with all three layers demanded up front. Extend the pb-21 prompt:

    Write a PowerShell script for a bulk operation via Microsoft Graph:
    set the department attribute for users listed in a CSV
    (columns: UserPrincipalName, NewDepartment).
    
    Mandatory structure:
    PHASE 1 — VALIDATE: check CSV headers exactly match; every UPN
    well-formed and resolvable in Entra; NewDepartment non-empty and in
    the allowed list passed as a parameter; duplicates flagged. Any
    failure: write a validation report and EXIT before any change.
    PHASE 2 — ROLLBACK CAPTURE: for every valid row, fetch and write
    current state (UPN, current department) to rollback_[timestamp].csv.
    Exit if this file cannot be written.
    PHASE 3 — DRY RUN (default mode): print the full change list
    (UPN: old -> new) and a count summary. Make no changes unless
    -Execute is explicitly passed.
    PHASE 4 — EXECUTE: only with -Execute; per-row try/catch, failures
    logged and skipped, final summary (changed / skipped / failed).
    Also produce: Undo-BulkChange.ps1 that replays rollback_*.csv.
    
  2. Validate the CSV — trust nothing from a spreadsheet. Run phase 1 alone first. The failures it should catch loudly:

    VALIDATION FAILED — 3 issues, no changes made:
    Row 14: UPN "j.smith@corp .com" contains whitespace
    Row 89: UPN not found in tenant: "mwilliams@corp.com"
    Row 90/91: duplicate UPN "achen@corp.com" with different values
    Report: validation_20260806_0912.csv
    

    Send the report back to the CSV's author; do not "fix a few rows yourself" — that makes you the owner of their data quality forever.

  3. Confirm the rollback file exists and is sane. Open it. Row count matches valid input rows; prior values look plausible (a column of blanks may itself be correct — but know that before, not after). This file is the operation's insurance policy; it is written even if you never execute.

  4. Read the dry run like it is the change. The dry-run output is your last cheap exit. Check the count first ("did I expect 312?"), then scan for the surprising: VIP accounts, service accounts, values changing that should be no-ops. Ten minutes here is the whole discipline.

  5. Execute in a pilot slice, verify, then full run. -Execute against the first 10 rows (or one department), verify in the admin console — the actual console, not your script's own success message — then run the remainder. Keep the per-row log.

  6. Verify the end state independently. Re-query the platform for all affected objects and diff against intended state:

    Import-Csv .\input.csv | ForEach-Object {
      $u = Get-MgUser -UserId $_.UserPrincipalName -Property Department
      if ($u.Department -ne $_.NewDepartment) {
        "{0}: expected {1}, got {2}" -f $_.UserPrincipalName,
          $_.NewDepartment, $u.Department } }
    

    Zero output is the goal; every line is a follow-up.

  7. Test the rollback before you need it. In the pilot phase, actually run Undo-BulkChange.ps1 against one object and confirm restoration. An untested rollback script is a hope, not a control. Then file everything — input CSV, validation report, rollback file, dry-run output, execution log — with the change record.

Make it yours

  • On-prem AD shopsame phases with the ActiveDirectory module; -WhatIf gives you phase 3 nearly free, and rollback capture uses Get-ADUser -Properties on every target attribute you plan to touch.
  • Exchange Online bulkthrottling is the extra enemy: have the generated script batch with delays and resume from a progress file, or a 2,000-mailbox run dies at 800 with no record of where.
  • Graph API at scaleuse batch endpoints for speed, but keep per-item error capture; a batched 20-item request that half-fails must decompose into per-item log rows, or your execution log lies.

Quality check

  • Default mode is dry run. Execution requires an explicit flag; a script that changes state when run bare fails review, whoever wrote it.
  • Rollback captured before change, tested in pilot. Both halves — captured and tested — are checklist items with initials.
  • Counts reconcile at every phase. Input rows = validated + rejected; validated = rollback rows; dry-run count = execute count = verified count. Any mismatch stops the run.
  • Console verification, not script self-report. The script saying "312 succeeded" is a claim; the platform showing the new values is a fact (the pb-27 principle, applied here).
Warning

Bulk-operation CSVs are PII by nature — names, UPNs, departments, sometimes term dates; store them and the rollback files in the change record's restricted location, not your desktop, and strip real identifiers before pasting samples into an external assistant while building the wrapper.

Key Takeaway:

Validate loudly, dry-run with your eyes open, and write the tested rollback before the first change — AI makes these three layers nearly free to build, which removes the last excuse for running bulk operations without them.

This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in