Module 6: Promotion, Rollback, and Documented Delivery

3. Reviewing changes as diffs, AI included

Description

By the end of this lesson you will be able to review any workflow change before it reaches production, reading its diff —the exact list of what changed— with judgment, not by eye. You're going to understand what a pull request is and why it's the mandatory review checkpoint for a change, and you're going to know how to review something new and delicate: workflows an AI created or modified inside your instance. The principle you're going to install is short and non-negotiable: the AI proposes, Git records, the human approves the diff before the change reaches prod.

This matters because promoting without reviewing is promising without reading. In lesson 2 you saw safe promotion starts with "did you review the diff of what you're promoting?" This lesson is that step, in detail. And it arrives at a particular moment in history: n8n 2.0 lets AI assistants build and edit workflows inside your instance. That multiplies the number of changes passing through your hands and makes review more important, not less: when a machine can generate twenty changes in an afternoon, the human reviewing the diff is the last —and sometimes the only— line between a good idea and a production disaster.

Connection to the module: lesson 2 moved the change forward (promoting); this one puts quality control before that move. Here you use the clean diff Module 3's normalization left you readable, and you set the stage for lesson 4, where an AI is really going to build workflows against a non-prod environment. This lesson answers the question lesson 4 makes urgent: if an AI touched the workflow, how do I know it didn't break anything before promoting it? The answer is the same diff review you apply to any change, with a couple of extra precautions you learn here.

What a diff is, and why it's your review tool

You already saw diffs in Module 2, but it's worth defining the word well, because it's the star of this lesson.

A diff —short for difference— is the exact list of what changed between two versions of a file: which lines got added, which got removed, which got modified. It isn't the whole file; it's just what moved. Git shows it to you with a visual format that reads at a glance: added lines carry a + and usually appear green, removed ones carry a - and appear red, and what didn't change appears gray, as context.

Think of it as the "spot the difference" game between two nearly identical drawings. Instead of describing both complete drawings to you, the diff points directly: "here, this tree that wasn't here before; there, this cloud that disappeared." It saves you comparing everything to find what moved. When you review an order-triage change, you don't read the whole JSON's hundreds of lines: you read the three the diff highlights, and you know exactly what's being proposed.

The command you already know produces it:

git diff HEAD~1 workflows/order-triage.json

This shows you what changed in order-triage.json between the previous version (HEAD~1, "one commit before the tip") and the current one. It's the same tool from Module 2's lesson 4, now serving a weighty decision: approving or not a change before it touches production.

Why Module 3's normalization makes this review possible

Stop a moment on something that was effort in Module 3 and is reward here. If your workflows' JSON weren't normalized —volatile fields removed, keys sorted, readable format with --pretty— the diff would be unreadable. A one-line change would show up buried among dozens of noise lines: a versionId that changed on its own, a different meta.instanceId, keys reordered randomly. Reviewing that would be impossible, and review would die from being useless.

That's why Module 3 insisted so much on normalization: it wasn't neatness for neatness's sake, it was building review's foundation. A clean diff is what makes it possible for a human to actually review. When in lesson 2's example the diff showed "only the threshold, 5000, and nothing else," that "and nothing else" is normalization's gift. Keep this connection: the discipline of cleaning the JSON and the discipline of reviewing the change are the same discipline, three modules apart.

The pull request: the mandatory review checkpoint

Now let's go up a step. git diff in your terminal is the tool; the pull request is the ritual turning it into a team practice.

A pull request —often shortened to PR— is a formal change proposal saying: "I want these changes to go into the main branch; please review them first." It lives on GitHub (or similar platforms), shows the proposal's complete diff, and gives another person —or you yourself, calmly, on another day— a place to approve or request changes before the proposal gets merged. Nothing reaches the main branch without going through there.

Think of it as the quality control at the end of a production line, before the product leaves the factory. The part got manufactured (the change got built on a branch), but it doesn't ship straight to the customer: it first goes through a station where someone inspects it against a checklist, approves it or sends it back. The pull request is that inspection station for your workflows. And the golden rule, the one separating a serious team from an improvised one, is: nothing gets promoted to prod without going through that station.

The cycle, in its simplest form, is this:

  1. You make the change on a branch. Not directly on the main branch: on a separate branch —remember Module 2's branches— which is like a separate workbench where you build the proposal without touching what's in production.
  2. You open a pull request toward the main branch. GitHub shows you the complete diff of what you're proposing.
  3. The diff gets reviewed. Someone reads it —ideally another person; if you work alone, yourself with fresh eyes— verifies the change does what it says and nothing more, and leaves comments or approves it.
  4. It gets merged (or fixed). If the diff looks good, it merges into the main branch. If something doesn't add up, the adjustment gets requested and it's reviewed again.

Only after the change is on the main branch, reviewed and approved, does it get promoted —with lesson 2's import:workflow. The pull request is the door; promotion is walking through the door. Without the door, any change enters production without anyone having looked at it, and that's exactly what a deployment avoids.

Working alone still deserves a pull request

You might think: "if it's just me, what's the point of a pull request? I made the change, I know what it does." It's a reasonable objection, and it has an answer worth gold.

The pull request, even alone, does three things a direct commit doesn't. First, it forces you to look at your own change with fresh eyes, separate from the moment you wrote it —and it's astonishing how many of your own mistakes you spot when the diff shows them to you neatly, hours after you made them. Second, it leaves a record: the PR stays as a note of what changed, why, and when it got approved; it's documentation that writes itself. Third, it trains you for the team: the day you work with more people, the ritual is already your habit, not something you have to learn under pressure.

Personally, I, Mike, review my own changes in a pull request even on single-person projects, especially when the change touches something going to production. Not out of ceremony: because the "me who writes" and the "me who reviews" are, in practice, two different people, and the second one catches what the first one missed.

How to read a workflow's diff with judgment

Having the diff isn't the same as knowing how to review it. Reviewing means asking the change questions. These are the ones a system owner asks every diff before approving it:

  • Does the change do what the message says? If the commit says "raise the threshold to 5000," the diff should show that and only that. If it also changed a CRM endpoint nobody mentioned, there's a mismatch between what's said and what's done, and that's an alarm.
  • Did something you didn't expect change? This is review's heart. A clean diff (thanks to normalization) makes any unexpected change jump out. If you see a URL, a credential, a config value changing that the change shouldn't touch, stop and understand why before approving.
  • Did a secret slip through? Even though Module 3's discipline makes it hard for a secret to reach the JSON, review is the second net. Search the diff for token-shaped strings —sk-, Bearer , long keys, password. A secret in a diff is an absolute stop.
  • Is the change reversible? Would you know how to go back if this change breaks something? If the diff touches something you wouldn't know how to undo, that's information about the change's risk, and maybe about needing a more careful rollback plan (lesson 5).

Notice the question doing the heavy lifting: "did something unexpected change?" A good workflow diff is boring: it shows exactly the change you announced, not one line more. The day the diff surprises you is the day review saved you. And that's why a clean diff matters so much: in a noisy diff, the surprise hides among the noise; in a clean diff, it has nowhere to hide.

Worked example: reviewing an order-triage change

Let's see a real review, with Cumbre. Someone —a person, or an AI, doesn't matter for this example— proposes a change to order-triage: "handle the case of orders with no associated customer." You open the diff before approving the promotion.

Step 1 — Look at the diff. From the repository, with the change already on its branch:

git diff main feature/handle-missing-customer -- workflows/order-triage.json

What to expect: the diff shows you what changed between the main branch (main) and the proposal's branch (feature/handle-missing-customer), only for order-triage.json. Suppose you see something like this:

       {
         "parameters": {
-          "conditions": "={{ $json.customerId }}"
+          "conditions": "={{ $json.customerId ?? 'unknown' }}"
         },
         "name": "Check customer",
         "type": "n8n-nodes-base.if"
       },
+      {
+        "parameters": {
+          "url": "={{ $env.CRM_URL }}/customers/lookup",
+          "method": "GET"
+        },
+        "name": "Lookup missing customer",
+        "type": "n8n-nodes-base.httpRequest"
+      },

Step 2 — Ask it the questions. Go through the diff with the list:

  • Does it do what it says? The message was "handle orders with no associated customer." The diff shows two things consistent with that: a condition now tolerating an absent customerId (using ?? 'unknown') and a new node looking up the missing customer in the CRM. It matches. Good.
  • Did something unexpected change? Go through line by line. There's no modification outside what the change announced: the threshold wasn't touched, nor the AI Agent, nor another URL. The diff is boring in the good sense. Good.
  • Did a secret slip through? The new node uses $env.CRM_URL —a reference to an environment variable, not a hardcoded value— and there's no plaintext token. Good.
  • Is it reversible? The change adds a node and adjusts a condition; going back would mean removing the node and restoring the condition, which is exactly what a git revert would do. Reversible. Good.

Step 3 — Decide. All four questions pass. The diff is consistent with its intent, hides no surprises, leaks no secrets, and is reversible. You approve the pull request, it merges into main, and now —not before— the change is ready to be promoted to staging and, after its test, to prod.

Stop on the order: you reviewed before promoting, not after. The diff was your inspection; the pull request, your quality control station. If in step 2 any question had failed —a plaintext secret, a URL changed with no explanation— you would have requested a fix instead of approving, and production would never have known about the problem.

The three kinds of change you'll see in a workflow diff

Not every change looks the same in the diff, and recognizing the types helps you review faster. In a workflow's JSON, a change almost always falls into one of three categories, and each deserves a different eye:

  • Parameter change. A value inside a node gets modified: a threshold from 1500 to 5000, a URL, an AI Agent prompt. In the diff it looks like a - line and its + replacement, inside a parameters block. It's the most common and easiest change to review: you read the old and new values, and decide if it makes sense. The key question here is one of judgment: is 5000 a reasonable threshold for Cumbre?
  • Structural change. A node gets added or removed. In the diff it looks like an entire + block (a new node object, with its name, type, and parameters) or a - one (a node disappearing). It requires more care: a new node can introduce an external call, a credential, a side effect. Ask yourself what that node does, not just that it's there.
  • Connection change. How the nodes link to each other changes, without touching the nodes themselves. In the diff it lives in the JSON's connections section, and it's the trickiest one, because a reordered connection can change the workflow's flow —what runs before what— without any node looking different. A diff that only touches connections deserves extra attention: the behavior may have changed even though the nodes are the same.

Recognizing the type orients your review. A parameter change is mostly business judgment; a structural one, about what new capability enters; a connection one, about whether the flow got silently altered. When you open a diff, the first useful question is "what type of change is this?" because the answer tells you where to focus your attention.

Reviewing what an AI did

Now the topic making this lesson special. n8n 2.0 lets an AI assistant —Claude, ChatGPT, Cursor— build and edit workflows inside your instance, through the MCP server you study in depth in lesson 4. That changes review's landscape, and it's worth understanding exactly what changes and what doesn't.

What doesn't change is the essential part: a change made by an AI is a change, and it goes through the same door as any other. The AI proposes; Git records the diff; a human reviews and approves it before it reaches prod. The diff review you just practiced is identical whether the change comes from a person or a machine. That's the good news, and it's the heart of why this guide had you learn to version and review before touching AI: you already have the net making AI safe.

What does change are three things making an AI change's review more careful, not less:

First: the AI generates more, and faster. A person makes a thought-out change; an AI can propose five variants in a minute. The volume goes up, and with it the temptation to "approve in bulk" without reading. Resist that temptation. Every diff reaching prod deserves the same eyes, whoever it comes from. If the AI proposes a lot, you review a lot; the solution isn't reviewing less, it's the AI proposing against an environment where its volume does no harm —dev, never prod— and only the reviewed part gets promoted.

Second: the AI sometimes changes more than you asked for. You ask it "add a node for the missing customer case" and, along the way, it "improves" another node's name, reorders a connection, or adjusts an unrelated value. Those collateral changes are exactly what "did something unexpected change?" catches. With an AI, that question goes from important to critical: the clean diff is your defense against changes the AI made "on its own initiative" without you asking.

Third: the AI doesn't understand business consequences. The AI can produce a technically correct change that's a disaster for Cumbre —lowering the manual-review threshold to 100 pesos, sending every order to review and swamping the team, for example. The diff looks clean, the JSON is valid, and the change is still bad. Here the AI can't help you: only a human who knows Cumbre's business knows 100 is an absurd threshold. Human review isn't just technical; it's about judgment, and business judgment is exactly what the AI doesn't have.

The safe loop, then, is this —lock it in, because it's the principle governing lessons 3 and 4:

   the AI          Git            the human        gets promoted
 proposes    →   records     →     reviews the  →   to staging
 (in dev)        the change        diff, approves    and to prod

The AI is a powerful, fast collaborator, but it isn't the one who signs off. The one who signs off is the human who read the diff. That signature —the pull request's approval— is what separates "I let an AI touch my system" from "I used an AI to build faster, with the same safety as always."

Why the diff is the best way to review an AI

There's a deep reason the diff is the perfect tool for reviewing an AI's work, and it's worth naming.

When you ask an AI something in natural language, the instruction is fuzzy —"handle weird orders better"— and the response can be anything within that margin. Without a diff, you'd have to trust the AI understood what you meant, or reread the whole workflow to discover what it did. The diff removes that uncertainty: it shows you, with line precision, exactly what the AI did, with no interpretation. It doesn't tell you what the AI says it did; it tells you what it did.

That difference —between what the AI reports and what actually changed— is where the problems live. An AI can confidently claim "I added handling for the missing customer" and, in the diff, have also deleted an important connection. The AI's text wouldn't tell you that; the diff would. That's why the rule isn't "trust what the AI explains to you," it's "read the diff of what the AI did." The diff is the source of truth about the change; the AI's explanation is, at best, a summary, and at worst, an optimistic version.

Common mistakes

Reviewing the entire JSON instead of the diff (practical). What happens: someone, to "review thoroughly," opens the whole order-triage.json and tries to read it top to bottom hunting for the change. They get lost among hundreds of lines, tire out, and end up approving without truly finding what moved. Why it happens: it seems like "reviewing everything" is more rigorous than reviewing the diff. It's the opposite. How to spot it: if you're reading workflow lines that didn't change, you're spending attention where there's nothing to review. How to fix it: review the diff, not the file. The diff is precisely what changed, which is the only thing there is to decide to approve or not. Reading the whole file isn't more rigorous; it's less effective, because fatigue makes you overlook exactly what matters.

Approving a pull request without reading the diff because "I trust who made it" (conceptual). What happens: someone approves a teammate's —or an AI's— change without opening the diff, because they trust the source. One day that trust lets through a mistake the diff would have shown at a glance. Why it happens: trust feels like enough, and reading the diff feels like distrust. It isn't: reviewing isn't distrusting, it's a deployment's normal process. How to spot it: if you approve PRs without opening the diff, you're not reviewing, you're rubber-stamping. How to fix it: always read the diff, no matter who made it. Review isn't a judgment on the person; it's a control on the change. The best engineers ask for their code to be reviewed precisely because they know anyone makes mistakes, themselves included.

Trusting what the AI says it did, instead of reading what it did (conceptual, AI-specific). What happens: someone asks the AI for a change, the AI answers "done, I added X and Y," and the person promotes based on that description without looking at the diff. It turns out the AI also touched Z, which broke something. Why it happens: the AI's explanation is fluent and convincing, and gives the sense you already know what changed. How to spot it: if your knowledge of what changed comes from the AI's text and not the diff, you trusted the summary. How to fix it: the AI proposes, the diff tells the truth. Read the diff of every AI change as if the AI had explained nothing to you; its explanation is a clue, not a guarantee. The gap between what the AI says and what it does is where problems live.

Letting the AI's volume lower the review standard (conceptual, AI-specific). What happens: the AI proposes ten changes in an afternoon, carefully reviewing ten diffs is work, and someone starts "approving fast" to not fall behind the machine's pace. Review quality collapses exactly when the most changes are going through. Why it happens: the human tries to match the AI's speed in review, which is impossible and counterproductive. How to spot it: if you approve faster when there are more changes, the volume is beating you. How to fix it: the review standard doesn't drop with volume; what drops is how many changes you let the AI propose at once. The AI builds against dev at its pace; you promote only what you reviewed at yours. The machine's speed is for building, not for skipping the control.

Exercises

Exercise 1 — Review a diff with the list. You get this proposed diff for order-triage.json. Go through it with the four review questions and decide whether you'd approve it or request changes:

       {
         "parameters": {
-          "url": "={{ $env.CRM_URL }}/orders",
+          "url": "https://crm.cumbre.example/orders",
           "method": "POST",
-          "authentication": "genericCredentialType"
+          "authentication": "none"
         },
         "name": "Register order in CRM",
         "type": "n8n-nodes-base.httpRequest"
       }
See solution

You'd request changes; you don't approve it. Going through the list:

  • Does it do what it says? We don't know what the message said, but the diff does two worrying things that would rarely be the declared intent.
  • Did something unexpected change? Yes, two serious things. First, the URL went from $env.CRM_URL (an environment variable, which changes per environment) to a hardcoded production URL (https://crm.cumbre.example/orders). That breaks portability between environments: that workflow would now point at production's CRM even in dev and staging. Second, authentication went from genericCredentialType (uses a credential) to none (no authentication). That either breaks the call, or —worse— leaves it unprotected.
  • Did a secret slip through? There's no plaintext token, but hardcoding the production URL is a close cousin of the problem: it puts environment configuration where it shouldn't be.
  • Is it reversible? Technically yes, but both changes are alarm signals that need understanding before continuing.

This diff is the perfect example of why review happens: it looks small, but hides two decisions that would break environment separation and authentication. A "boring" diff would have been safe; this one is anything but boring.

Why it works: the exercise trains you that no change gets a pass just for being short. The two problems —the hardcoded URL and the none authentication— are exactly the kind of thing a review catches and a blind promotion lets through into production.

Exercise 2 — Justify the pull request for a single person. A teammate who works alone tells you: "Pull requests are large-team bureaucracy; I commit straight to main and that's it, why would I review myself?" Write them a three or four-sentence answer giving at least two concrete reasons for using pull requests even working alone.

See solution

A possible answer:

"I get the point, but a pull request helps even alone, for two concrete reasons. First: it forces you to look at your own change as a diff, separate from the moment you wrote it, and you're going to catch your own mistakes you didn't see while making them —the 'you who reviews' sees what the 'you who writes' overlooked. Second: it leaves a record of what changed and why, which is documentation that writes itself and that you're going to thank yourself for in six months when you don't remember why you touched that node. And a third: the day you work with more people, the habit's already in place, you don't have to learn it under pressure. It isn't bureaucracy; it's the step turning 'I changed it' into 'I changed it and reviewed it.'"

Why it works: the objection is common and reasonable, and the answer doesn't dismiss it with "do it because," but with concrete benefits applying to a single person: fresh-eyes review, automatic record, and future habit. It's the same logic behind why versioning alone is still worth it.

Exercise 3 — Review the AI. You asked an AI, via MCP on your dev instance, "add error handling to the CRM node in order-triage." The AI responds: "Done, I added a retry node and error handling on the CRM node." Before promoting, what exactly do you do, and why isn't the AI's description enough?

See solution

What you do: you export the workflow the AI modified in dev, commit it on a branch, and open the diff against the previous version. Then you review it with the four questions: does the diff show the error handling you asked for (and only that)? did something unexpected change? did any secret slip through? is it reversible? Only if the diff passes review do you approve and promote to staging.

Why the AI's description isn't enough: because the description is what the AI says it did, and the diff is what it actually did, and the gap between those two things is where problems live. The AI might have added the error handling and also touched something else —reordered a connection, changed a value, deleted a node— without mentioning it. The description is an optimistic summary; the diff is the source of truth. Also, the AI doesn't know whether the error handling it added makes sense for Cumbre's business; that judgment is yours to make while reviewing.

Why it works: this exercise installs the central reflex of working with AI on your instance: never promote based on what the AI told you; promote based on the diff you reviewed. The AI proposes and builds fast; the human reads the diff and signs off. That division of labor is what makes AI safe in a production system.

Summary and next step

In this lesson you installed the quality control going before every promotion: reviewing the change as a diff. You understood a diff is the exact list of what changed —lines with + and -— that Module 3's normalization is what makes it readable, and that reviewing means asking the change four questions: does it do what it says? did something unexpected change? did a secret slip through? is it reversible? You met the pull request as the mandatory quality control station —the door a change goes through before merging and getting promoted— and why it's worth it even working alone: fresh-eyes review, automatic record, and a habit for the team. And you faced the module's new topic: reviewing workflows an AI created or modified. The essential part doesn't change —the AI proposes, Git records, the human approves the diff before prod— but review becomes more careful for three reasons: the AI generates more and faster, it sometimes changes more than you asked for, and it doesn't understand business consequences. The diff is the best way to review it because it shows what the AI did, not what it says it did.

Before moving on you should be able to: read a workflow diff and apply the four questions to it; explain what a pull request is and why it's mandatory even alone; and describe the safe loop for AI changes —propose in dev, record in Git, approve the diff, promote.

Lesson 4 closes AI's loop. Up to here you assumed "an AI modified the workflow"; now you're going to see how it does it: n8n's instance-level MCP server, which lets an AI assistant build and edit workflows inside your n8n. You're going to learn to point it at a non-prod environment —dev, never production— to understand the complete safe loop, its limits and permissions, and why the isolated environments you set up in Module 4 are exactly the safety net making it possible to let a machine touch your workflows without fear.

Resources