Module 4: Observability Logging Auditing Monitoring
1. Module introduction: seeing in order to operate
Description
By the end of this lesson you'll be able to explain what observability is and how it differs from monitoring, you'll know the four pieces that make up an automation's observability layer —logs, auditing, metrics, and health with alerts—, and you'll have a clear map of the module's eight lessons. You'll also meet Terra Market, the marketplace that will accompany you throughout the module, and you'll understand the concrete question this entire module exists to answer: "what happened with order 4471?", asked nine days after that order passed through your system.
This matters for a very unromantic reason: in production, sooner or later someone will ask you about an individual case, and the answer "I don't know" has a cost. Not the abstract cost of looking bad, but the concrete cost of a customer who leaves, a refund that gets paid without knowing whether it was warranted, or an entire afternoon of three people reconstructing by hand what a system should be able to tell you in thirty seconds. A system that runs is not the same as a system you can explain. Observability is the difference between the two.
Connection to the module: this lesson doesn't instrument anything yet. It's the map and the framing. Here you define the problem (nobody can reconstruct what happened to an order), you meet the company and the instance you'll be working on, and you locate where this module ends and where its neighbors begin —because observability touches almost everything else and it's easy to get lost—. Lessons 2 and 3 build the system's memory: what your workflow records about itself (structured logging) and what you can answer a human six months later (audit trail). Lessons 4 and 5 make the leap from the case to the trend and the state: metrics and health checks. Lesson 6 turns those metrics into a measurable promise and into an alert that doesn't wear anyone out. Lesson 7 takes all of that out of n8n before it deletes itself. And lesson 8 brings it together into Terra Market's complete observability layer.
Order 4471
Let's start with the problem, not with the definition. The definition without the problem is forgotten in a week.
It's Tuesday. A support email comes in with a complaint: the customer of order 4471 says they never received anything. Nine days have passed since they made the purchase. The store has the order on record, charged and confirmed. The ERP —the system where Terra Market's inventory, invoicing, and logistics live— doesn't have it. It's nowhere to be found. And between the store and the ERP there's exactly one n8n workflow, order-sync, that's been running for eight months and that nobody had complained about.
The first reaction is reasonable: open n8n's execution list and look for that order's execution. And there the first wall appears. The execution is no longer there. It didn't fail, nobody deleted it, there was no incident: n8n removed it on its own, as it's designed to do, because old executions get pruned so the database doesn't grow without limit. With Terra Market's volume —around 4,000 executions a day—, the visible history doesn't come anywhere near nine days. We'll come back to why in a moment, because the exact number surprises a lot of people.
Suppose, for the sake of argument, that the execution were still there. Would it be enough? You'd have the data dump of each node: what went in, what came out. With patience you could reconstruct the path. But notice what you would not have:
- Why the workflow made the decision it made. If an
Ifnode sent the order down the "customer without credit" branch, the dump shows you it came out that way, but it doesn't tell you what value it was compared against or where that value came from if it came from an intermediate call that's no longer there. - What happened in the other workflows.
order-syncdoesn't work alone. After it comeinventory-updateandshipment-notify. Each one is a separate execution, with its own identifier, and nothing in the interface connects them to each other. Finding order 4471's complete thread means opening three lists and cross-referencing them by eye. - Whether anyone touched anything. If on July 12 someone edited
order-syncto "fix a small detail" and that broke the push to the ERP, an execution's dump won't tell you.
That's the full problem. It's not that a tool is missing: it's that the system left no trace of itself. It ran, it did things, and it noted down nothing of what it was doing. Everything this module builds comes out of that.
A note before moving on, because it's worth saying early: when you finish the module, the question "what happened with order 4471?" will be answered in under three minutes, with a single query, thirty days after the fact. That's the concrete standard we'll measure everything you build against. If a piece doesn't move you closer to that result, it's excess.
Worked example: the same question, with and without observability
Let's look at both versions of that Tuesday morning, side by side. There's no code yet; the contrast is what matters.
Version without observability. You open n8n, you search the execution list, there's nothing from nine days ago. You ask in the team channel if anyone remembers anything from July 14. Nobody does. You go into the ERP's database and search for any record with a number resembling 4471; there isn't one. You open the order-sync workflow and read it node by node, trying to imagine which branch that order might have taken. Since you can't reproduce it, you end up doing the only thing left: you ask the customer to confirm the details, you create the order by hand in the ERP, and you close the ticket. Time spent: between two and four hours of two people. What you learned about the cause: nothing. What you guaranteed about it not happening again: nothing. And here's the most expensive part: you don't know whether order 4471 was the only one. There could be forty orders in the same situation and you'd have no way of knowing.
Version with observability. You open the query you left ready and filter by order_id = "4471" in your run_log table. Eleven rows come out, ordered by date, one for each event your workflows recorded about that order:
2026-07-14T10:02:11Z order-sync order.received order_id=4471 channel=web
2026-07-14T10:02:11Z order-sync order.validated order_id=4471 items=3
2026-07-14T10:02:12Z order-sync erp.push.attempt order_id=4471 attempt=1
2026-07-14T10:02:42Z order-sync erp.push.failed order_id=4471 attempt=1 reason=timeout
2026-07-14T10:02:52Z order-sync erp.push.attempt order_id=4471 attempt=2
2026-07-14T10:03:22Z order-sync erp.push.failed order_id=4471 attempt=2 reason=timeout
2026-07-14T10:03:32Z order-sync erp.push.attempt order_id=4471 attempt=3
2026-07-14T10:04:02Z order-sync erp.push.failed order_id=4471 attempt=3 reason=timeout
2026-07-14T10:04:02Z order-sync order.dropped order_id=4471 reason=erp_unreachable
2026-07-14T10:04:02Z inventory-update skipped order_id=4471 reason=no_erp_reference
2026-07-14T10:04:02Z shipment-notify skipped order_id=4471 reason=no_erp_reference
What to expect from a reading like this. At a glance you have the complete story: the order came in fine, it validated fine, and the three attempts to push it to the ERP timed out. At 10:04:02 the workflow dropped it, and the two following workflows skipped it because they had no ERP reference. Nobody found out. And with the same query, swapping order_id = "4471" for reason = "erp_unreachable" and a date range, in ten seconds you know how many more orders fell the same way that morning. If it was thirty-seven, you now have an understood incident instead of a mystery; if it was just one, you know that too.
Notice three things about that table, because they're the skeleton of the whole module.
First: every row has the order_id. That field is what lets you join eleven events that occurred across three different workflows and three different executions. Without it, you'd have eleven loose rows that form no story. It's the thread, and lesson 2 gives it a name: correlation identifier.
Second: there's a reason field. It doesn't just say what happened, it says why. erp.push.failed without reason=timeout would leave you halfway there: you'd know it failed but not whether it was the network, credentials, or the ERP rejecting the content. The decision and its motive are what turn a record into an explanation.
Third: none of this is the order's data dump. There's no customer name, no address, no purchase line items. There's the identifier, the event, the decision, and the motive. That's deliberate, and it's one of the most important design decisions of lesson 2: logging everything is nearly as useless as logging nothing, because a log that contains the entire universe can't be read, can't be searched, and —when there's personal data inside— becomes a legal problem.
Observability and monitoring: they're not synonyms
Now, the definitions, which after the problem make sense on their own.
Monitoring is watching things you decided in advance to watch. You define what to measure, you set a threshold, and the system alerts you when it's crossed. "Tell me if the instance stops responding." "Tell me if the error rate goes above 2%." Monitoring answers questions you already knew you were going to ask.
Observability is the property of a system that lets you answer questions you had not anticipated, without having to modify it or redeploy it. "Why do mobile-channel orders take three times as long on Monday mornings?" Nobody set up an alert for that in advance. But if your system left enough of a trail —events with their identifier, their decision, their duration, and their motive—, the answer is already there and you just have to look for it.
The image that works best for me, Mike: monitoring is the car's dashboard. It has the temperature gauge, the oil light, the fuel level. Someone at the factory decided that those three things deserve a light, and they work very well for what they were designed for. Observability is the black box: it doesn't warn you about anything while you drive, but when something went wrong it lets you reconstruct the entire trip, minute by minute, even to answer questions nobody had asked before the accident.
You need both, and in that order of dependency: monitoring is built on top of observability, not the other way around. You can't alert on a metric that nobody is logging. That's why this module starts with logs (lesson 2) and ends with alerts (lesson 6), and not the reverse.
A warning about this is worth it, because it's the most common ordering mistake: the temptation when you reach production is to install a pretty panel with charts first. The panel is the last piece, not the first. A panel fed by data nobody designed shows metrics that mean nothing, and it gives a false sense of control that's worse than having no panel. First you decide what to log. Then you log. Then you measure. And in the end, if it's needed, you draw.
The four pieces of the layer
Everything you'll build in this module fits into four boxes. It's worth keeping them separate in your head from the start, because they do different things and get confused all the time.
1. Logs (lesson 2). The diary of what your workflow decided. It answers: what did the system do with this case? It's the most granular piece and the most useful for debugging. It lives a short time if you don't ship it out.
2. Audit trail (lesson 3). The formal record of who did what, when, and to what. It answers: what can I tell a customer, legal, or my boss? It resembles the log but has a different owner, a different level of trust, and a different retention period —usually much longer—.
3. Metrics (lessons 4 and 6). Numbers aggregated over time. They answer: how is the system doing overall, and are we meeting what we promised? They're no good for investigating a case; they're good for detecting that there's a problem and for knowing whether it improved.
4. Health and alerts (lessons 5 and 6). The traffic light of the now and the warning when it turns red. They answer: is it working right now, and who finds out if it stops working?
A table to lock in the difference, because confusion among the four is the number-one source of poorly built observability layers:
| Piece | Question it answers | Grain | Who reads it | How long it's kept |
|---|---|---|---|---|
| Log | What did the system decide with this case? | An event | Whoever operates and debugs | Short (days to weeks) |
| Audit | Who did what, when, to what? | A verifiable fact | Support, legal, management | Long (months to years) |
| Metric | How's the trend going? | An aggregate | Whoever operates, and the business | Medium-long, already summarized |
| Health / alert | Is it fine right now? | A state | Whoever's on call | Instant (plus its history) |
The classic mistake is using one for another's job. Trying to answer "is the instance alive?" by reading ten thousand log rows is losing the morning. Trying to answer "what happened with order 4471?" by looking at a success-rate chart is impossible: the chart says 99.2% came out fine and has no way of telling you which one was the 0.8%.
Terra Market: this module's company
The whole module works on the same made-up company, for the same pedagogical reason as always: if every lesson debuts a new context, you spend your energy understanding the scenario instead of the concept.
Terra Market is a mid-sized Latin American marketplace. Around 60 people. It sells a bit of everything —home goods, small electronics, stationery— through its own online store, and every sale has to cross three systems that don't talk to each other: the store, the ERP where inventory and invoicing live, and the carrier that picks up and delivers. n8n is the glue between the three.
In production there are 18 active workflows, which together do around 4,000 executions a day. You're the one who operates that instance. You didn't build all of it —several workflows were put together by people who are no longer around—, but when something breaks, the call is for you.
Three of those 18 workflows are the module's protagonists, because they form the chain that touches an order:
| Workflow | What it does | Triggered by |
|---|---|---|
order-sync | Takes a new order from the store and pushes it to the ERP | Store webhook |
inventory-update | Deducts stock in the ERP and reflects it back in the store | Chained after order-sync |
shipment-notify | Requests a shipping label from the carrier and notifies the customer | Scheduled, every 15 minutes |
And these are the identifiers you'll see in every lesson. They're in English on purpose, like the code: it's the ecosystem's convention and it's what you'll find in any team in the region.
| Identifier | What it is |
|---|---|
order_id | The order number. The thread that connects everything. In the module's case, 4471. |
sku | The product code within the order. |
execution_id | The identifier n8n gives to each execution. |
run_log | The table where your workflows write their operational events. |
audit_log | The table where who did what gets recorded. |
Terra Market's numbers —60 people, 18 workflows, 4,000 executions— are reasonable hypotheses for practice, not market data. If tomorrow you operate a real marketplace, the numbers will be different; what transfers is the way of thinking about the problem. And that specific volume does matter for a calculation we'll do right now.
Why the execution from nine days ago is no longer there
It's worth clarifying this in lesson 1, because it's the root of the case and because the real number is surprising.
n8n saves each execution in its database, and so that database doesn't grow until it fills the disk, it has a pruning mechanism that deletes old executions automatically. The official documentation confirms that pruning is enabled by default and that it's governed by two limits, whichever of the two is met first:
EXECUTIONS_DATA_MAX_AGE— the age, in hours, after which a finished execution is deleted. Its default value is336, that is, 14 days.EXECUTIONS_DATA_PRUNE_MAX_COUNT— the maximum number of executions kept in the database. Its default value is10000. When it's exceeded, they're deleted from oldest to newest.
And EXECUTIONS_DATA_PRUNE is the master switch, whose default value is true: pruning comes turned on.
Now Terra Market's calculation, which is where the surprise is. A lot of people read "14 days" and assume they have two weeks of history. But with 4,000 daily executions, the cap of 10,000 is reached in two and a half days. That's the limit that bites first, and by a lot. When the order 4471 complaint arrived, the execution had been deleted for almost a week, and no alarm sounded, because the system was doing exactly what it was told.
Think of it like a mailbox with a capacity for ten thousand letters. The rule says "throw out letters older than fourteen days," but it also says "don't accumulate more than ten thousand." If four thousand letters arrive daily, the mailbox fills up before any letter turns fourteen days old, and the rule that ends up governing is the capacity one. Age never gets a chance to apply.
Two consequences come out of that, and they'll run through the entire module:
First: your investigation horizon isn't what you think. Before trusting the execution history for anything serious, calculate how many days your volume gives you against EXECUTIONS_DATA_PRUNE_MAX_COUNT. It's a division, and it gives a number that's almost always smaller than intuition. Your instance's effective values have to be verified in your own configuration: they may be overridden, and on n8n Cloud they depend on the plan.
Second, and this is the one that justifies the module: raising the limits is not the solution. The obvious temptation is to set EXECUTIONS_DATA_MAX_AGE to a huge number and be done. But that just moves the problem: the database grows, queries slow down, backups get heavy, and you still can't search by order_id —because the execution history isn't designed for that—. The right answer isn't to keep more executions; it's to keep separately, and in a queryable format, the little information you actually need. That's lesson 2.
An honest nuance, and a fairly useful one: the documentation confirms that annotated executions —the ones carrying a tag or a rating— are never pruned. It's a legitimate emergency exit for manually preserving a specific execution you're investigating. It's not an observability strategy, because it requires someone to know in advance which one will matter, but it's worth keeping in your pocket. We'll pick it up again in lesson 3.
Where this module ends: the boundaries
This module touches several neighbors, and I want to mark the limits now so you don't look here for things that are well explained elsewhere, or vice versa.
Boundary with server operations. The self-hosting and operations guide, in its module 6, covers how the instance is operated and debugged: reading container logs with docker compose logs, tuning N8N_LOG_LEVEL and N8N_LOG_OUTPUT, checking the /healthz and /healthz/readiness endpoints, enabling the worker health check in queue mode, and making Docker restart whatever goes down. All of that looks at the process: is the engine on and responding?
This module looks at the workflow: what does your automation record about itself so someone can answer what happened with an order? They're two layers of the same stack and both are needed, but they don't substitute for each other. An instance with /healthz returning 200 could be silently dropping 8% of orders, and the health check will never find out, because the process is perfectly healthy; what's broken is what the workflow decides. The reverse too: the best run_log in the world is no use to you if the container is down and there's nobody executing anything. When in lesson 5 I talk about health checks I'll lean on what that guide already established and build on top —external monitoring and the business heartbeat—, without repeating it.
Boundary with correctness alerts. The workflow contracts and idempotency guide, in its module 6, already deals with where failures should alert and why: the difference between a transient failure and a terminal one, alert fatigue, who the owner that responds is, and with what urgency. It's a design decision about the system's correctness, and it's well resolved there. That same lesson explicitly delegates the observability infrastructure to this guide, so we're on both sides of the same agreement.
Lesson 6 of this module does not re-explain why alerting on everything is counterproductive. It takes for granted that you already know it and attacks the other half, which is the operational one: how you write an SLA in measurable terms, how you choose an alert's threshold from the real metrics you logged in lesson 4, and what to do with the time window and the error budget. If you're missing the theory of "what deserves an alert," go to that guide first; here we work on the "starting from which number."
Boundary with error handling. Module 2 of this same guide covers how the system recovers from a failure: automatic retries, error output, global error workflows, failure notifications. This module covers what gets logged and what gets measured. They're complementary and the order is intentional: module 2 teaches you to react, this one teaches you to know. When in lesson 2 you log erp.push.failed attempt=2, the mechanism that produced that second attempt is module 2's; what we're doing here is leaving a record that it happened.
Boundary with debugging. Module 3 of this guide uses the replay engine to reproduce an execution that still exists. This module deals with the case where it no longer exists, or where it exists but doesn't tell you what you need to know. They're the two halves of the same investigation.
Boundary with performance. Module 6 of this guide finds the slow node and tunes throughput. Here we measure duration to detect that there's slowness and to set a threshold; the diagnosis of why a node is slow belongs over there.
The map of this module
| Lesson | What it solves |
|---|---|
| 2 | Structured logging: which fields deserve to be logged, how the event is built, and the identifier that connects three workflows |
| 3 | Audit trail: the difference from the operational log, what's kept to answer a human, and for how long |
| 4 | Execution metrics: volume, error rate, and duration — and why the average lies and you have to look at the percentile |
| 5 | Health checks and uptime: how to know the instance is alive before a customer says so, with an external observer |
| 6 | SLA and alerts: what a measurable promise is, how the threshold is chosen, and how you keep the alert from becoming noise |
| 7 | Getting logs and metrics out of n8n: why they shouldn't live inside, where to send them, and with what node |
| 8 | Project: Terra Market's complete observability layer, measured against the order 4471 question |
The order isn't accidental. First you log (2 and 3), because without data there's nothing. Then you aggregate (4), because the trend is built on top of the records. Then you watch (5 and 6), because a threshold needs a history so as not to be an invented number. And in the end you export (7), because none of the above is any use if it deletes itself in two and a half days. The project (8) closes the loop.
If an image helps: the first four lessons give you memory, the next two give you reflexes, and the seventh gives you permanence. An operator without memory can't explain; without reflexes can't react; and without permanence loses both things every week.
What this module deliberately does not cover
It's worth saying early.
It's not a guide to a specific observability tool. You won't install or deeply configure a third-party stack. You'll learn what to expose and in what shape, so you can connect it to whatever your company already uses. Where a specific tool is unavoidable —Prometheus in lesson 7— I treat it as an example of the pattern, not as the subject.
It's not a course in SQL or in time series. You'll see simple queries against your own tables, with the detail needed to understand them, but modeling analytical data is another path.
It doesn't cover regulatory compliance. Lesson 3 talks about retention and personal data with an engineering criterion, not legal advice. What your country's law requires about how long to keep a record and what can be stored is a conversation with whoever handles the legal side at your company, and it's worth having before designing the schema, not after.
It doesn't cover the cost of AI in production. Tokens, budget, and the current models are module 7 of this guide. If you have workflows with AI nodes, their cost metrics are instrumented with the same techniques from lesson 2, but the criterion of what to look at is over there.
Common mistakes
Confusing "runs" with "is fine" (conceptual). What happens: someone looks at the execution list, sees a column of greens, and concludes the system works. And yet the orders aren't reaching the ERP. Why it happens: an execution's status in n8n says whether the workflow finished without throwing an error, not whether it did the right thing. A workflow that catches an error, silently discards it, and moves on ends up green with full propriety. In the order 4471 case, it's perfectly possible the execution would have appeared as successful. How to detect it: ask yourself, for each workflow, "is there any path by which this flow ends green without having done its job?". There almost always is, and it's almost always a poorly handled error branch. How to fix it: stop measuring health with the execution's color and start measuring it with business events —"order confirmed in the ERP"— that you log on purpose. It's exactly what lesson 2 does.
Starting with the chart panel (practical). What happens: a dashboard tool is connected to n8n's database on day one, six pretty charts are built, and within a week nobody looks at them because none of them answers a question anyone has. Why it happens: the panel is the visible, gratifying part; the data that feeds it is the boring part. How to detect it: look at your current panel —if you have one— and for each chart ask yourself "what decision do I make differently based on what it shows?". If the answer is "none," that chart is decoration. How to fix it: reverse the order. Write first the three or four questions people actually ask you —"did this order reach the ERP?", "how many didn't arrive this week?", "is it taking longer than usual?"—, and build backward from them. A panel with two charts that answer real questions is worth more than one with twenty that don't.
Believing that n8n's execution history is your logging system (conceptual). What happens: it's assumed that since n8n saves each execution with all its data, observability is already there and there's nothing more to do. Why it happens: an execution's dump is genuinely rich —you have each node's input and output— and it gives the sense that everything's there. How to detect it: try to answer a single aggregate question with it, like "how many orders were dropped for erp_unreachable last week?". You won't be able to: the execution list isn't queried that way, and besides, half of that week has already been pruned. How to fix it: treat the execution history for what it is —a short-term debugging tool, excellent for the recent case— and build the queryable, durable record separately. The two coexist; neither replaces the other.
Exercises
Exercise 1 — Calculate your real horizon. With the default values we saw (EXECUTIONS_DATA_MAX_AGE=336 hours and EXECUTIONS_DATA_PRUNE_MAX_COUNT=10000), calculate how many days of execution history each of these three instances really has, and say which of the two limits rules in each case:
(a) An instance with 200 executions a day. (b) Terra Market's instance, with 4,000 executions a day. (c) An instance with 40,000 executions a day.
See solution
(a) 14 days; age rules. 10,000 ÷ 200 = 50 days to fill the quota, but at 14 days (336 hours) executions start getting deleted by age. The count limit never gets a chance to apply. This is the instance for which the intuition of "I have two weeks" is correct.
(b) 2.5 days; count rules. 10,000 ÷ 4,000 = 2.5 days. Far short of 14. This is Terra Market's case and the reason the order 4471 execution wasn't there: when the complaint arrived, it had been deleted for about six and a half days.
(c) 6 hours; count rules, by a lot. 10,000 ÷ 40,000 = 0.25 days. An instance like that has a history of one morning. If someone reports a problem after lunch, the morning's execution is already gone.
Why it works: the exercise forces you to do the division almost nobody does. The practical lesson is that the limit that rules depends on your volume, and that past a certain traffic level the number of days stops having any relation to the 14 that EXECUTIONS_DATA_MAX_AGE's default suggests. If your instance resembles (b) or (c), you can't rest any serious investigation on the execution history. Remember too to verify the effective values in your own configuration: they may be overridden, and on Cloud they depend on the plan.
Exercise 2 — Classify the question. For each of these six questions, say which of the four pieces answers it —log, audit, metric, or health/alert— and in one sentence why:
(a) Is the instance responding right now?
(b) Why did order 4471 never reach the ERP?
(c) How many orders were dropped due to ERP problems last month?
(d) Who disabled the shipment-notify workflow on Friday afternoon?
(e) Are we meeting the promise to sync 99% of orders in under 5 minutes?
(f) Did the sync time get worse since Tuesday's deployment?
See solution
(a) Health. It's a question of instant state, with a yes-or-no answer. It's the traffic light, not the diary.
(b) Log. It's a question about an individual case and about the decisions the system made with it. It needs the fine grain of one event per step, with its order_id and its reason.
(c) Metric. It's an aggregate: a count over a time window. It can be computed from the logs, but what you're after is the number, not the cases.
(d) Audit. It's a question about a person and an administrative action, not about data processing. Neither the operational log nor the metrics answer it: you need a record of who did what.
(e) Metric, in its SLA form. It's an aggregate with a threshold and a window declared in advance. It's exactly lesson 6's material.
(f) Metric, comparing two windows. And here there's a nuance worth gold: as you'll see in lesson 4, this question answered with the average can give "no, all the same" while the customers' real experience got dramatically worse. You have to look at it with percentiles.
Why it works: notice that of six questions, only one is the log's and one is the audit's, but they're the two that hurt most when they're missing. The metrics tell you there's a problem; the log tells you which one; the audit tells you who. If your instinct assigned (b) to "metric" or (d) to "log," it's worth rereading the four-pieces table: that confusion is what produces systems where there are lots of charts and no answers.
Exercise 3 — Locate the boundary. For each of these five tasks, say whether it belongs to this module, to the self-hosting guide (instance operation), to the contracts guide (alert policy), or to module 2 of this guide (error handling):
(a) Deciding that a stuck refund should wake someone up and a timeout that recovered should not.
(b) Configuring Retry On Fail on the node that calls the ERP.
(c) Logging in a table that order 4471 was dropped with reason=erp_unreachable.
(d) Making Docker restart the n8n container when it stops responding.
(e) Deciding that the slowness alert fires when the 95th percentile goes above 5 minutes for 15 minutes straight.
See solution
(a) Contracts guide, module 6. It's the design decision about what deserves to interrupt a person: the distinction between transient and terminal failure, and alert fatigue. It's already resolved there and this module doesn't repeat it.
(b) Module 2 of this guide. It's a recovery mechanism: how the system reacts to the failure. This module limits itself to leaving a record that the retry happened.
(c) This module, lesson 2. It's pure structured logging: the business identifier, the decision, and the motive.
(d) Self-hosting guide, module 6. It's process health and infrastructure self-recovery. Here we take it as known and build on top, in lesson 5, with external monitoring.
(e) This module, lesson 6. The what to alert on is contracts'; the starting from which number, measured how, for how long is ours, and it comes from lesson 4's metrics.
Why it works: if you got (a) and (e) as different things, you understood the module's subtlest boundary. Both talk about alerts, but one decides whether something deserves an alert and the other decides when it fires. Without the first, you alert on everything; without the second, you have a policy nobody knows how to implement because there's no number.
Summary and next step
In this lesson you saw the problem that gives the module its meaning: a customer complains about order 4471 nine days later, and nobody can say what happened —the execution no longer exists and, even if it did, it wouldn't record why the workflow decided what it decided—. You distinguished monitoring (watching what you decided in advance to watch) from observability (being able to answer questions you hadn't anticipated), and you saw that the first is built on top of the second, never the other way around. You separated the four pieces of the layer —logs, audit, metrics, and health/alerts— with their question, their grain, their reader, and their retention period. You met Terra Market, its 18 workflows, its 4,000 daily executions, and the three protagonist workflows (order-sync, inventory-update, shipment-notify). And you understood, with numbers, why the execution from nine days ago is no longer there: with EXECUTIONS_DATA_PRUNE_MAX_COUNT at 10000 by default and that volume, the real history is two and a half days, not the 14 that EXECUTIONS_DATA_MAX_AGE=336 suggests. Lastly you marked the boundaries with the self-hosting guide (the instance), the contracts one (alert policy), and module 2 (recovery).
Before moving on you should be able to: explain the difference between monitoring and observability with an example of your own; name the four pieces and which question each one answers; and calculate, for any instance, how many days of execution history it really has.
What comes next is the piece that holds up all the others. In lesson 2 you'll build the record that was missing: structured logging. You'll see why a log written in prose —"error processing the order"— can't be searched, counted, or aggregated, and how an event with shape —{ event, order_id, decision, reason, ts }— can. You'll decide which fields deserve to be logged and which are noise or risk. You'll set up the correlation identifier that connects order 4471's three separate executions into a single story. And you'll learn the correct pattern to emit it in n8n 2.0, which has an important constraint: the Code node builds the log object, but can't send it —that's done by a separate HTTP Request node—.
Resources
- Manage execution data — n8n Docs — the official page on execution pruning:
EXECUTIONS_DATA_PRUNE,EXECUTIONS_DATA_MAX_AGE(default336hours) andEXECUTIONS_DATA_PRUNE_MAX_COUNT(default10000), plus the note that annotated executions are never pruned. It's the source of this lesson's calculation; verify your instance's effective values. - Executions environment variables — n8n Docs — the complete table of execution variables with their types and default values, including what's saved on success, on error, and on manual executions.
- Monitor n8n — n8n Docs — the health endpoints and the metrics endpoint, worked on in lessons 5 and 7.
- Understand executions — n8n Docs — how n8n's execution lists work, their limits, and what can be searched in them.
- Release notes 2.x — n8n Docs — the version 2 history, useful for confirming which version you're comparing what this module says against.